Как объединить массив объектов в один массив, а затем отфильтровать дубликаты

#javascript #arrays #algorithm

Вопрос:

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

Наконец, все повторяющиеся элементы в массиве должны быть удалены, а также любые элементы с именем «name».

Ввод:

 const data = [
  {
    name: '10/20',
    Tyler: 1,
    Sonia: 0,
    Pedro: 0,
  },
  {
    name: '10/23',
    Tyler: 0.5,
    Sonia: 0.25,
    Pedro: 0.75,
    George: 0.5,
  },
];
 

Вывод:

 ["Tyler", "Sonia", "Pedro", "George"]
 

Это то, что я пробовал до сих пор:

 const mergedData = data.reduce((prev, cur) => {
  const obj = cur[0];
  const keys = Object.keys(obj);
  const names = keys.splice(1);
  return { names };
}, []);
 

Я пытаюсь захватить любое ключевое имя, отличное от «name», и добавить его в конечный массив. Однако именно здесь я застреваю, потому что получаю эту ошибку, TypeError: Cannot convert undefined or null to object

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

Ответ №1:

Один из вариантов — найти все ключи, помещенные в набор, и удалить name ключ

 const data = [
  {
name: '10/20',
Tyler: 1,
Sonia: 0,
Pedro: 0,
  },
  {
name: '10/23',
Tyler: 0.5,
Sonia: 0.25,
Pedro: 0.75,
George: 0.5,
  },
];

const set = new Set(data.reduce((acc, i) => [...acc, ...Object.keys(i)], []));
set.delete('name');
const result = [...set];

console.log(result); 

Ответ №2:

Если у вас есть доступ к методам ES6, вы можете сделать это с помощью набора (уникальные значения гарантируются при создании) и преобразовать его обратно в массив, если хотите, путем деструктурирования.

 data = [{name: '0', Tyler: '1', Dan: '2', Carl: '3'},  {name: '0', Tyler: '1', Dan: '2', Eric: '3', Danny: '4'}];

const output = (data) => {
  let output = [];

  // This makes sure you get each array and then strips just the keys as desired
  data.forEach(item => {
      output = output.
        concat(Object.keys(item))
  });

// This creates the set, strips our dups, and then spreads itself into an array
return [...new Set(output)]
    // Strip out the 'name' key as needed
    // NOTE: This should be a param instead of hard-coded, but this is easier to show
    .filter(res => res != 'name');
}

console.log(output(data)); 

Это должно быть довольно производительным, учитывая, что он перемещается по всему массиву только один раз, и каждый объект сам по себе не должен иметь миллионы свойств, вызывающих .keys() какие-либо проблемы.