Как я могу выполнить итерацию по массиву (фильтру)?

#javascript #arrays #object

#javascript #массивы #объект

Вопрос:

У меня есть такая структура JSON:

 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"},
          ]
        },
      ]
 

Мне нужно создать массив с некоторым условием. Если мое условие правильно, я буду нажимать элементы arr.rows.

Наконец, я хочу получить эту структуру:

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

Я пытаюсь сделать так

 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})
            }
          }
 

Комментарии:

1. Вы пытаетесь сгруппировать записи на arr основе их идентификатора? Как {id: "1", name: "Object1"} сопоставляется запись с {id: "1", name: "Group1"} таким образом, чтобы они оказались в одном объекте { Objects: "Object1", Groups: "Group1" } ?

2. Да, вы правы. Группировка по идентификатору.

Ответ №1:

Основываясь на комментариях и упомянутом вами ожидаемом конечном массиве объектов, я немного изменил вашу логику, чтобы она соответствовала ожидаемому результату.

Мой подход использует дополнительное пространство, но время o (nlogn) (не уверен, что это наиболее эффективно). Надеюсь, этот код поможет.

 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.
 

Ответ №2:

Вместо построения построения массива, создание объекта значительно упростило бы задачу. Вы можете использовать ключ id as для каждого объекта, чтобы вы могли легко найти объект, к которому хотите присоединить свойства.

Приведенный ниже фрагмент перебирает разные «столбцы». Если столбец соответствует критериям (является либо «Объектами», либо «Группами»), мы пройдемся по строкам столбца и добавим свойства к результирующему объекту.

 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);