Объединение вложенных объектов по ключу. JS

78
16 апреля 2022, 16:40

Есть объект

Объект 1
{
 1: {
        id:1, // id: совпадает с ключом данного объекта, уникальное значение для всех объектов
        name: 'test1', // name: слово на латинице и всегда уникально,
        value: 1, // значение которое и нужно синхронизировать
        ...//другие поля
   },
 2: {
        id:2, // id в данном объекте совпадает с ключом данного объекта
        name: 'test2',
        value: 1,
        ...//другие поля
   }
3: {
        id:3, // id в данном объекте совпадает с ключом данного объекта
        name: 'test3',
        value: 1,
        ...//другие поля
   }
 ...// объект может содержать до 200 вложенных объектов
}

далее по ходу выполнения программы появляется ещё такие объекты структурно похожие на данный, которые могут содержать поля name, которые уже встречались в предыдущем объекте. Например:

Объект 2
{
     50: {
            id:50, 
            name: 'what', 
            value: 2,
            ...//другие поля
       },
     51: {
            id:51, 
            name: 'test1', // данное имя встречалось в "объекте 1"
            value: 2,
            ...//другие поля
       }
     ...//объект может содержать до 200 вложенных объектов
 }
Объект 3
 {
      67: {
              id:67, 
              name: 'test2', 
              value: 3,
              ...//другие поля
           },
      68: {
              id:68, 
              name: 'test4',
              value: 3,
              ...//другие поля
           }
         ...//объект может содержать до 200 вложенных объектов
 }

Результат:

{
     51: {
            id:51, 
            name: 'test1', // данное значение было в "Объекте 1" и "Объекте 2" т.к. "Объекте 2" был взят в цикле позже чем "Объекте 1", то в результирующий взят объект из "Объект 2"
            value: 2, 
            ...//другие поля
        },
    67: {
            id:67, 
            name: 'test2', // из объекта 3
            value: 3,
            ...//другие поля
       },
    3: {
            id:3, 
            name: 'test3', // из объекта 1
            value: 1,
            ...//другие поля
       },
   50: {
            id:50, 
            name: 'what',  // из объекта 2
            value: 2,
            ...//другие поля
       },
   68: {
            id:68, 
            name: 'test4', // из объекта 3
            value: 3,
            ...//другие поля
       }
     ... // объект может содержать до 200 вложенных объектов
    }

Т.е. в результирующий объект нужно поместить только уникальные объекты по полю name. последние значение берётся из объекта который в цикле встретился последним. Порядок сортировки объекта не важен.

Answer 1

Идея простая: вначале подобавлять объекты в словарь, где ключем будет поле name, а потом словарь сконвертировать в результирующий объект

const obj1 = {
  1: {
    id: 1, // id: совпадает с ключом данного объекта, уникальное значение для всех объектов
    name: 'test1', // name: слово на латинице и всегда уникально,
    value: 1, // значение которое и нужно синхронизировать
  },
  2: {
    id: 2, // id в данном объекте совпадает с ключом данного объекта
    name: 'test2',
    value: 1
  },
  3: {
    id: 3, // id в данном объекте совпадает с ключом данного объекта
    name: 'test3',
    value: 1
  }
};
const obj2 = {
  50: {
    id: 50,
    name: 'what',
    value: 2
  },
  51: {
    id: 51,
    name: 'test1', // данное имя встречалось в "объекте 1"
    value: 2
  }
};
const obj3 = {
  67: {
    id: 67,
    name: 'test2',
    value: 3
  },
  68: {
    id: 68,
    name: 'test4',
    value: 3
  }
};
const accum = {};
function addObj(accum, obj) {
  for (let i in obj) {
    accum[obj[i].name] = {
      obj: obj[i],
      idx: i
    }
  }
}
function convertAccum(accum) {
  const res = {};
  for (let i in accum) {
    const obj = accum[i];
    res[obj.idx] = obj.obj;
  }
  return res;
}
addObj(accum, obj1);
addObj(accum, obj2);
addObj(accum, obj3);
const res = convertAccum(accum);
console.log(res);

P.S. Этот код будет работать если индексы в исходных объектах уникальны

Answer 2

Вы слышали об Object.assign(), Object.entries(), Object.fromEntries()?

// Входящие данные
let objA = { [1]: {name: '1' }, [2]: {name: '2'}, [3]: {name: '3'}, [4]: {name: '4'}};
let objB = { [5]: {name: '4' }, [6]: {name: '5'}, [7]: {name: '6'}, [8]: {name: '7'}};
let objC = { [9]: {name: 'a' }, [10]: {name: 'b'}, [11]: {name: 'c'}, [12]: {name: 'd'}};
// Зададим несколько констанций
const { entries: E, fromEntries: F, assign: A } = Object,
  [R,I,P] = [ a => [{},...a],
              ([name,data]) => [data.id,data],
              ([id,data]) => [data.name,A(data,{id})] ],
  N = o => F(E(o).map(P));
// Это всё, что вам нужно
let objR = F(E(A(...R([objA,objB,objC].map(N)))).map(I));

// На выходе получаем objR
// JSON.stringify и прочие .replace() здесь для форматирования вывода
// то есть, этот код в условие задачи не входит
console.log('obj = ',JSON.stringify(objR).replace(/(^{|},)/g,'$1\n').replace(/^"(\w+)":/mg,'[$1]:'));

READ ALSO
Как сделать цикл по времени в JS, чтобы выводились каждые 15 минут между двумя числами времени?

Как сделать цикл по времени в JS, чтобы выводились каждые 15 минут между двумя числами времени?

Столкнулся с проблемой циклаНе могу понять как написать его правильно

243
Как анимировать маршрут (path) на SVG карте?

Как анимировать маршрут (path) на SVG карте?

Есть SVG карта созданная на RaphaelКак можно анимировать маршрут между двумя кликами на карте, как например здесь

193
Сортировка в таблице

Сортировка в таблице

Использую такой код сортировка в таблицеВсе работает нормально, но есть один момент который хотелось бы улучшить

106
Прогресс-бар картинкой

Прогресс-бар картинкой

Опыта в php и css у меня всего пара месяцевВозникла необходимость сделать красивый прогресс-бар для браузерной онлайн-игры в виде картинкок(одна...

167