Kartik Solanki
Kartik Solanki

Reputation: 171

Javascript Reducing the Array to Desired Format

I am trying to reduce the array as efficiently as possible. My current array looks like this:

myArr = [
    {cat: "Wires", subCat: "Wires & Connection", description: "Demo Description for Green Wire", id: 4049, name: "green_wire"},
    {cat: "Wires", subCat: "Wires & Connection", description: "Demo Description for Red Wire", id: 1224, name: "red_wire"},
    {cat: "Fixtures", subCat: "Lights", description: "The Bullet FL2832B uplight casts a broad, flatteri…s include an included heavy-duty composite stake.", id: 1360, name: "bullet_lights"},
    {cat: "Fixtures", subCat: "Spot Lights", description: "Demo Description for Walkway Lights", id: 8602, name: "walkway_lights"},
    {cat: "Controls", subCat: "Power Sources", description: "Description for 600w SS Transformer", id: 7738, name: "600w_ss_transformer"},
    {cat: "", subCat: "", description: "Project Background Image", id: 8029, name: "bgImg"}
];

And I want to reduce this array to this format by sorting children based on "cat" first and then inside "cat", I want to sort the children based on "subCat". Something like this:

final = [
    {
        cat: "Wires",
        children : [
            {
                subCat: "Wires & Connection",
                children: [
                    {cat: "Wires", subCat: "Wires & Connection", description: "Demo Description for Green Wire", id: 4049, name: "green_wire"},
                    {cat: "Wires", subCat: "Wires & Connection", description: "Demo Description for Red Wire", id: 1224, name: "red_wire"}
                ]
            }
        ]
    },
    {
        cat: "Fixtures",
        children : [
            {
                subCat: "Lights",
                children : [
                    {cat: "Fixtures", subCat: "Lights", description: "The Bullet FL2832B uplight casts a broad, flatteri…s include an included heavy-duty composite stake.", id: 1360, name: "bullet_lights"}
                ]
            },
            {
                subCat: "Spot Lights",
                children : [
                    {cat: "Fixtures", subCat: "Spot Lights", description: "Demo Description for Walkway Lights", id: 8602, name: "walkway_lights"}  
                ]
            }
        ]
    },
    {
        cat: "Controls",
        children : [
            {
                subCat: "Power Sources",
                children: [
                    {cat: "Controls", subCat: "Power Sources", description: "Description for 600w SS Transformer", id: 7738, name: "600w_ss_transformer"}
                ]
            }
        ]
    }, 
    {
        cat: "",
        children : [
            {
                subCat: "",
                children: [
                    {cat: "", subCat: "", description: "Project Background Image", id: 8029, name: "bgImg"}  
                ]
            }
        ]
    }
]

So far, I have tried this but this organize the array only by "subCat". I want to nest it further down to "cat":

    const formatedObjects = objects.reduce((acc, d) => {
      const found = acc.find(a => a.subCat === d.subCat);
      const value = { 
        id: d.id,
        name: d.name,
        subCat: d.subCat,
        cat: d.cat,
        description: d.description
        }; // the element in data property
      if (!found) {
        acc.push({subCat:d.subCat, children: [value]}) // not found, so need to add data property
      }
      else {
        found.data.push(value) // if found, that means data property exists, so just push new element to found.data.
      }
      return acc;
    }, []);

Any idea how can i do this efficiently?

Upvotes: 1

Views: 131

Answers (1)

Seth MacPherson
Seth MacPherson

Reputation: 57

If optional chaining is available could do something like:

const array = [{
    cat: "Wires",
    subCat: "Wires & Connection",
    description: "Demo Description for Green Wire",
    id: 4049,
    name: "green_wire",
  },
  {
    cat: "Wires",
    subCat: "Wires & Connection",
    description: "Demo Description for Red Wire",
    id: 1224,
    name: "red_wire",
  },
  {
    cat: "Fixtures",
    subCat: "Lights",
    description: "The Bullet FL2832B uplight casts a broad, flatteri…s include an included heavy-duty composite stake.",
    id: 1360,
    name: "bullet_lights",
  },
  {
    cat: "Fixtures",
    subCat: "Spot Lights",
    description: "Demo Description for Walkway Lights",
    id: 8602,
    name: "walkway_lights",
  },
  {
    cat: "Controls",
    subCat: "Power Sources",
    description: "Description for 600w SS Transformer",
    id: 7738,
    name: "600w_ss_transformer",
  },
  {
    cat: "",
    subCat: "",
    description: "Project Background Image",
    id: 8029,
    name: "bgImg",
  },
];

const final = array.reduce((list, item) => {
  const {
    cat,
    subCat
  } = item;
  const hasList = !!list ? .[cat];
  const subList = list ? .[cat] ? .children.find(
    (child) => child.subCat === subCat
  );

  if (!hasList) {
    list[cat] = {
      cat,
      children: [{
        subCat,
        children: [item],
        count: 1,
      }, ],
    };
  } else if (!subList) {
    list[cat].children.push({
      subCat,
      children: [item],
      count: 1,
    });
  } else {
    subList.count += 1;
    subList.children.push(item);
  }

  return list;
}, {});

console.log(Object.values(final));

Upvotes: 1

Related Questions