Mikkel Bo
Mikkel Bo

Reputation: 74

Create a key map for all paths in a recursive/nested object array

I have an n levels deep nested array of tag objects with title and ID. What I'm trying to create is a an object with IDs as keys and values being an array describing the title-path to that ID.

I'm no master at recursion so my attempt below doesn't exactly provide the result I need.

Here's the original nested tag array:

const tags = [
  {
    title: 'Wood',
    id: 'dkgkeixn',
    tags: [
      {
        title: 'Material',
        id: 'ewyherer'
      },
      {
        title: 'Construction',
        id: 'cchtfyjf'
      }
    ]
  },
  {
    title: 'Steel',
    id: 'drftgycs',
    tags: [
      {
        title: 'Surface',
        id: 'sfkstewc',
        tags: [
          {
            title: 'Polished',
            id: 'vbraurff'
          },
          {
            title: 'Coated',
            id: 'sdusfgsf'
          }
        ]
      },
      {
        title: 'Quality',
        id: 'zsasyewe'
      }
    ]
  }
]

The output I'm trying to get is this:

{
  'dkgkeixn': ['Wood'],
  'ewyherer': ['Wood', 'Material'],
  'cchtfyjf': ['Wood', 'Construction'],
  'drftgycs': ['Steel'],
  'sfkstewc': ['Steel', 'Surface'],
  'vbraurff': ['Steel', 'Surface', 'Polished'],
  'sdusfgsf': ['Steel', 'Surface', 'Coated'],
  'zsasyewe': ['Steel', 'Quality']
}

So I'm building this recursive function which is almost doing it's job, but I keep getting the wrong paths in my flat/key map:

function flatMap(tag, acc, pathBefore) {
  if (!acc[tag.id]) acc[tag.id] = [...pathBefore];
  acc[tag.id].push(tag.title);

  if (tag.tags) {
    pathBefore.push(tag.title)
    tag.tags.forEach(el => flatMap(el, acc, pathBefore))
  }
  return acc
}

const keyMap = flatMap({ title: 'Root', id: 'root', tags}, {}, []);
console.log("keyMap", keyMap)

I'm trying to get the path until a tag with no tags and then set that path as value for the ID and then push the items 'own' title. But somehow the paths get messed up.

Upvotes: 2

Views: 1259

Answers (1)

Siva Kondapi Venkata
Siva Kondapi Venkata

Reputation: 11001

Check this, makePaths arguments are tags, result object and prefixed titles.

const makePaths = (tags, res = {}, prefix = []) => {
  tags.forEach(tag => {
    const values = [...prefix, tag.title];
    Object.assign(res, { [tag.id]: values });
    if (tag.tags) {
      makePaths(tag.tags, res, values);
    }
  });
  return res;
};

const tags = [
  {
    title: "Wood",
    id: "dkgkeixn",
    tags: [
      {
        title: "Material",
        id: "ewyherer"
      },
      {
        title: "Construction",
        id: "cchtfyjf"
      }
    ]
  },
  {
    title: "Steel",
    id: "drftgycs",
    tags: [
      {
        title: "Surface",
        id: "sfkstewc",
        tags: [
          {
            title: "Polished",
            id: "vbraurff"
          },
          {
            title: "Coated",
            id: "sdusfgsf"
          }
        ]
      },
      {
        title: "Quality",
        id: "zsasyewe"
      }
    ]
  }
];

console.log(makePaths(tags));

Upvotes: 1

Related Questions