Как посчитать все уникальные значения в массиве объектов?

#javascript #arrays #object

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

Вопрос:

Я хочу создать массив со значением uniqueDate в моем массиве. Итак, если у меня есть этот массив:

 const arr = [
      {
        name: "Edward",
        date: "24 March"
      },
      {
        name: "Banana",
        date: "12 March"
      },
      {
        name: "Edward",
        date: "23 March"
      },
      {
        name: "Edward",
        date: "23 March"
      }
    ]
 

… тогда результат будет примерно таким:

 [
    {name:"Edward", uniqueDate: 2, totalSubmit: 3},   
    {nama: "Banana",uniqueDate: 1, totalSubmit: 1}
]
 

Первая уникальная дата равна 2, потому что у нас 2 разные даты: 24 марта и 23 марта. Я пытался использовать reduce , но у него есть некоторые проблемы.

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

1. Пожалуйста, покажите нам, что вы уже пробовали.

2. Например, у меня есть этот массив: const arr = [ { нама: «Эдвард», дата: «24 марта» }, { нама: «Банан», дата: «12 марта» }, { нама: «Эдвард», дата: «23 марта» }, { нама: «Эдвард», дата: «23 марта» }, { нама: «Боб», дата: «1 марта» }, { нама: «Пэм», дата: «1 марта» }, {нама: «Анна», дата: «19 марта» }, { нама: «Джейк», дата: «12 марта» } ]

3. Я уменьшил его в два раза, const reducedSales = arr.reduce((acc, item) => { var previousItem = acc.find(FindItem => (FindItem[‘nama’] === item[‘nama’]) amp;amp; (FindItem[‘date’] === item[‘date’])); // если предыдущий элемент имеет значение false, то это означает, что другой распространитель Nama if (!previousItem) { acc.push({…item, totalSubmit: 1 }) } else { previousItem.totalSubmit } возвращает acc; }, [])

4. и еще одно сокращение, const update = reducedSales.reduce((acc, item) => { var previousItem = acc.find(FindItem => FindItem[‘nama’] === item[‘nama’]); // если предыдущий элемент имеет значение false, то это означает, что другой распространитель Nama, если (!previousItem) { acc.push({…item, hariKerja: 1 }) } else { previousItem.hariKerja } возвращает acc; }, []) console.log(обновление)

5. @AndrewL64 это выходные данные: [ { нама: ‘Эдвард’, дата: ’24 марта’, итоговая отправка: 1, Харикерджа: 2 }, { нама: ‘Банан’, дата: ’12 марта’, итоговая отправка: 1, Харикерджа: 1 }, { нама: ‘Боб’, дата: ‘1 марта’, Итоговая отправка: 1, Харикерджа: 1 }, { нама: ‘Пэм’, дата: ‘1 марта’, Итоговая отправка: 1, Харикерджа: 1 }, { нама: ‘Анна’, дата: ’19 марта’, Итоговая отправка: 1, Харикерджа:1 }, { нама: ‘Джейк’, дата: ’12 марта’, Итоговая отправка: 1, Харикерджа: 1 } ]

Ответ №1:

Вы можете использовать a Map для сбора дат, которые идут с именем (проверьте правильность написания в примере данных!), А затем вы можете перебирать эти записи карты, чтобы получить как длину массива дат, так и количество уникальных (через Set):

 const arr = [{name: "Edward",date: "24 March"},{name: "Banana",date: "12 March"},{name: "Edward",date: "23 March"},{name: "Edward",date: "23 March"}];

let map = new Map(arr.map(o => [o.name, []]));
for (let {name, date} of arr) map.get(name).push(date);
let result = Array.from(map.entries(), ([name, dates]) => 
    ({name, uniqueDate: new Set(dates).size, totalSubmit: dates.length})
);
console.log(result); 

Если имя свойства, по которому нужно сгруппировать, содержит специальные символы, такие как пробел, то:

 const arr = [{"Full Name": "Edward",date: "24 March"},{"Full Name": "Banana",date: "12 March"},{"Full Name": "Edward",date: "23 March"},{"Full Name": "Edward",date: "23 March"}];

let map = new Map(arr.map(o => [o["Full Name"], []]));
for (let o of arr) map.get(o["Full Name"]).push(o.date);
let result = Array.from(map.entries(), ([name, dates]) => 
    ({"Full Name": name, uniqueDate: new Set(dates).size, totalSubmit: dates.length})
);
console.log(result); 

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

1. Привет, большое спасибо за вашу помощь. Если я могу добавить еще 1 вопрос, что, если в имени моего объекта есть пробел? Например, вместо имени имя объекта является полным именем. Вместо даты имя объекта «Создано в».

2. для (пусть {name, date} arr) map.get(name).push(date); Ошибка типа: не удается прочитать свойство ‘push’ неопределенного значения, поэтому для контекста имя моего объекта выглядит как «Полное имя» и «Создано в».

3. Таким образом, фактический массив выглядит примерно так: const arr = [{«Полное имя»: «Эдвард»,»Создано в»: «24 марта»}]; и т. Д

4. См. Дополнение к ответу.

Ответ №2:

Вы можете вызвать функцию reduce, чтобы затем создать пару ключ-значение для каждого имени, где оно содержит имя, a Set уникальных дат и totalSubmit . Наконец, вы можете получить значения этого объекта и сопоставить его с размером уникальных дат.

 const arr = [{ name: "Edward", date: "24 March" }, { name: "Banana", date: "12 March" }, { name: "Edward", date: "23 March" }, { name: "Edward", date: "23 March" }];
    
const temp = arr.reduce((acc, { name, date }) => {
   acc[name] = acc[name] || { name, dates: new Set(), totalSubmit: 0 };
   acc[name].totalSubmit  ;
   acc[name].dates.add(date);
   return acc;
}, {});
    
const result = Object.values(temp).map(({ name, dates, totalSubmit}) => ({ name, uniqueDate: dates.size, totalSubmit }));
     
console.log(result); 

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

1. Большое спасибо за ваш ответ! Могу я добавить еще 1 вопрос? Что, если в имени моего объекта есть пробел? Пример: вместо «name» его «Полное имя»

2. @EdwardTanoto Я предполагаю, что это «Полное имя» будет уникальным. в этом случае мы можем использовать key = name.split(‘ ‘).join(‘_’), который превращает Edward Tanoto в Edward_Tanoto