Horus
Horus

Reputation: 77

How can I iterate over an array(filter)?

I have this JSON structure:

const arr = [
        {
          id: "TaskStatuses",
          rows: [
            {id: "1", name: "Success"},
            {id: "2", name: "Error"},
          ]
        },
        {
          id: "Objects",
          rows: [
            {id: "1", name: "Object1"},
            {id: "2", name: "Object2"},
          ]
        },
        {
          id: "Groups",
          rows: [
            {id: "1", name: "Group1"},
            {id: "2", name: "Group2"},
          ]
        },
      ]

I need to create array with some condition. If my condition correctly I will push elements arr.rows.

Finally i want to get this structure:

[
{
  Objects: "Object1",
  Groups: "Group1"
},
  {
    Objects: "Object2",
    Groups: "Group2"
  }
]

I try to do like this

let sites = []
    for (let el in arr) {
            if (arr.id == "Objects") {
              for (let item of el.rows) {
                sites.push({Objects: item.name})
              }
            }
            if (arr.id == "Groups") {
              for (let item of el.rows) {
                sites.push({Groups: item.name})
            }
          }

Upvotes: 0

Views: 82

Answers (2)

3limin4t0r
3limin4t0r

Reputation: 21110

Instead of building building an array, building an object would simplify things a lot. You can use the id as key for each object so you can easily find the object you want to attach properties to.

The snippet bellow loops through the different "columns". If the column matches the criteria (being either "Objects" or "Groups"), we'll loop through the rows of the column and attach the properties to the resulting object.

const arr = [{
  id: "TaskStatuses",
  rows: [
    {id: "1", name: "Success"},
    {id: "2", name: "Error"},
  ]
}, {
  id: "Objects",
  rows: [
    {id: "1", name: "Object1"},
    {id: "2", name: "Object2"},
  ]
}, {
  id: "Groups",
  rows: [
    {id: "1", name: "Group1"},
    {id: "2", name: "Group2"},
  ]
}];

const sites = {};
const whitelist = new Set(["Objects", "Groups"]);;
for (const column of arr) {
  if (!whitelist.has(column.id)) continue;
  for (const row of column.rows) {
    sites[row.id] ||= {};
    sites[row.id][column.id] = row.name;
  }
}
console.log(sites);

Upvotes: 0

Viraj Jadhav
Viraj Jadhav

Reputation: 119

Based on comments and your mentioned expected final object array, I modified your logic a bit to match the expected output.

My approach uses extra space, but o(nlogn) time (not sure if this is most efficient). Hope this code helps.

let firstArr = [], secondArr = [];
arr.forEach((d, i) => {
  if (d.id === "Objects") {
    firstArr.push(...d.rows);
  }
  if (d.id === "Groups") {
    secondArr.push(...d.rows);
  }
});
//console.log(firstArr, secondArr);

//sorting, if necessary based on id of each arr[i].rows
firstArr.sort(function (a, b) {
  return a.id - b.id || a.name.localeCompare(b.name);
});
//sorting, if necessary based on id of each arr[i].rows
secondArr.sort(function (a, b) {
  return a.id - b.id || a.name.localeCompare(b.name);
});
let index = 0,
  size = Math.min(firstArr.length, secondArr.length);
let finalArr = [];
for (index; index < size; index++) {
  if (firstArr[index].id === secondArr[index].id) {
    finalArr.push({
      Objects: firstArr[index].name,
      Groups: secondArr[index].name,
    });
  }
}
//console.log(finalArr); ////this is your final Array.

Upvotes: 1

Related Questions