@fessss

Как правильно отфильтровать массив массивов объектов?

const arr = [
    [
        {
            id: 1,
            name: 'test'
        },
        {
            id: 2,
            name: 'test2'
        },
        {
            id: 3,
            name: 'test3'
        }
    ],
    [
        {
            id: 4,
            name: 'test4'
        },
        {
            id: 5,
            name: 'test5'
        },
        {
            id: 6,
            name: 'test3'
        }
    ]
]


Мне нужно:
1) соединить два массива в один. Я сделал через flat();
2) отфильтровать таким образом, чтобы из первого массива удалился элемент, если например в массиве втором есть с таким же свойством. Вот что-то уже туплю сильно. подскажите, ребят. Спасибо
  • Вопрос задан
  • 228 просмотров
Решения вопроса 2
sergiks
@sergiks Куратор тега JavaScript
♬♬
Если речь идёт только об уникальности свойства name, можно создать объект, где это свойство будет ключом, а последний встретившийся объект с этим свойством – значением. Более поздние объекты с повторным свойством nameперезаписывают собой более ранние. В конце остаётся вытащить все значения из этого объекта:
Object.values(
  arr.reduce(
    (acc, c) => {
      c.forEach(o => acc[o.name] = o);
        // получается объект acc:
        //    "test":  {id: 1, name: 'test'},
        //    "test2": {id: 2, name: 'test2'},
        //    "test3": {id: 3, name: 'test3'},
        // ...
      return acc;
    },
    {}
  )
);


Update. в комментариях выснили, что требуется уникальность не одного, а набора свойств. Тогда принцип тот же, но в качестве ключа использовать некий хэш или отпечаток этих свойств.
Самый простой вариант склеить строки значений. Но возможны коллизии типа {"name": "Stan", code: "dart"} и {"name": "Stand", code: "art"} — оба дадут отпечаток "Standart" и посчитаются идентичными.

Немного лучше удалить из копии объекта св-во id, и перевести в JSON. Тут слабое место – порядок свойств. Если у одного из объектов свойства поменяют местами, алгоритм сочтёт их разными.
Object.values(
  arr.reduce(
    (acc, c) => {
      c.forEach(o => {
        const source = Object.assign({}, o);
        delete source.id;
        const hash = JSON.stringify(source);
        acc[hash] = o;
      });
      return acc;
    },
    {}
  )
);
Ответ написан
Abr_ya
@Abr_ya
Что-то красивое решение на ночь глядя не получается.
А ведь хочется, чтобы работало с любым набором свойств!
Навскидку такой вариант:
1) объединить массивы,
2) создать массив id и массив свойств,
3) пройти по массиву свойств - оставить индексы только уникальных элементов,
4) собрать массив уникальных элементов на основе индексов полученных в п.3 из массивов, полученных в п.2.

Выглядит это примерно так:
const arr1 = [
    {id: 1, name: 'test'},
    {id: 2, name: 'test2'},
    {id: 3, name: 'test3'}
];
const arr2 = [
    {id: 4, name: 'test4'},
    {id: 5, name: 'test5'},
    {id: 6, name: 'test3'}
];

const newArr = [...arr1, ...arr2];
console.log(newArr);
const idArr = newArr.map((item) => (item.id));
console.log(idArr);
const dataArr = newArr.map((item) => {
    delete item.id;
    return JSON.stringify(item);
});
console.log(dataArr);
uniqueIdArr = dataArr.map((item,index) => {
    if (!dataArr.slice(0,index).includes(item)) return index;
}).filter(id => (id !=undefined));
console.log(uniqueIdArr);
uniqueArr = uniqueIdArr.map(id => ({id: idArr[id], ...JSON.parse(dataArr[id])}));
console.log(uniqueArr);

Если не пойдет как решение, то может какие-то идеи пригодятся.)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы