найти повторяющиеся свойства obj и вернуть свойство с наименьшим количеством - PullRequest
0 голосов
/ 02 июля 2018

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

[
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1}
{count: 10, category: 8},
...
]

Что мне нужно, так это найти наименьшее количество из каждой категории и вернуть новый массив объектов. Я мог бы легко сделать это, используя простой старый цикл, я думаю, но я хотел бы использовать map (). Reduce или какой-то другой новый метод func.

Ответы [ 4 ]

0 голосов
/ 02 июля 2018

Использование Array#reduce() для создания объекта с категориями в качестве ключей и объектов в качестве значений, а затем получить массив, используя Object#values()

const res= Object.values(
   data.reduce((acc, {count, category}) => {
      const o = acc[category] || (acc[category] = {count, category});
      o.count = Math.min(o.count, count);   
      return acc;
    },{})
);

console.log(JSON.stringify(res))
<script>
var data= [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}

]
</script>
0 голосов
/ 02 июля 2018

Есть много способов сделать это. Один будет:

function filterLowestCounts(a) {
  const lowestCountsByCategory = a.reduce(
    (result, { count, category }) => ({
      ...result,
      [category]: Math.min(count, result[category] || Number.MAX_SAFE_INTEGER)
    }),
    {}
  )

  return Object.entries(lowestCountsByCategory).map(
    ([category, count]) => ({ count, category: Number(category) })
  )
}

Назовите это так:

filterLowestCounts([
  {count: 1, category: 4},
  {count: 2, category: 4},
  {count: 3, category: 2},
  {count: 4, category: 2},
  {count: 5, category: 8},
  {count: 6, category: 8},
  {count: 7, category: 1},
  {count: 8, category: 1},
  {count: 9, category: 1},
  {count: 10, category: 8},
])

Результат:

[
  {count: 7, category: 1},
  {count: 3, category: 2},
  {count: 1, category: 4},
  {count: 5, category: 8},
]
0 голосов
/ 02 июля 2018

Это выглядит немного грязно, но это был бы подход, чтобы сделать это в одну строку, используя конкатенацию и вложение функций массива, фильтровать, отображать и уменьшать:

let array = [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}
]

let result = array.filter((value, index, self)=>{
     return self.findIndex((innerValue)=>{
         return innerValue.category == value.category}) === index;
 }).map((item)=>{
     return { count: array.filter((innerItem)=>{
         return innerItem.category == item.category
        }).reduce((min, item)=>{
         return (item.count < min) ? item.count : min; }).count, category: item.category};
 });
 
 console.log(result);
0 голосов
/ 02 июля 2018
var list = [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}
];

function groupAndGetMin(list, keyGetter, valueGetter) {
    const map = new Map();
    list.forEach((item) => {
        const key = keyGetter(item);
        const value = valueGetter(item);
        const o = map.get(key);
        if (!o) {
            map.set(key, item.count);
        } else {
            map.set(key, Math.min(o, value));
        }
    });
    return map;
}
var result = groupAndGetMin(list, l => l.category, i => i.count);

// это вернет Map (4) {4 => 1, 2 => 3, 8 => 5, 1 => 7}

...