Печать из вложенного массива с использованием map, уменьшения и фильтрации в javascript

#javascript #node.js #arrays

#javascript #node.js #массивы

Вопрос:

Конечная цель — получить по одному для каждого имени в следующем массиве. (Аналогично закомментированным строкам внизу приведенного ниже фрагмента)

Если есть одно и то же имя, только с наибольшим количеством, а если есть повторяющееся количество, только с более высокой версией.

Я попытался использовать комбинацию map, reduce. Пожалуйста, помогите мне решить эту проблему.

 //Original array
var arr = [
  {'name': 'b', 'version': '103', 'count': 10}, 
  {'name': 'a', 'version': '0.1b', 'count': 73}, 
  {'name': 'b', 'version': '109', 'count': 67}, 
  {'name': 'a', 'version': '1.0.3', 'count': 100}, 
  {'name': 'a', 'version': '2.1.0', 'count': 100}, 
  {'name': 'c', 'version': 'a103', 'count': 30}, 
  {'name': 'c', 'version': 'a111', 'count': 100}
];

//expected console output
// { name: 'a', version: '2.1.0', count: 100 }
// { name: 'b', version: '109', count: 67 }
// { name: 'c', version: 'a111', count: 100 }
 

Во-первых, как «часть» этого процесса, я попытался получить «а» из массива.

 var filteredArr = arr.filter(item => item.name === 'a');

var m = Math.max(...(filteredArr.map(({count}) => count))),
  maxes = arr.map(({count}) => count).reduce((p,c,i,a) => c ==  m ? p.concat(i) : p,[]);
console.log(maxes);
 

Я ожидал получить [3, 4] сверху, но он печатает [3, 4, 6] .

=====

Дополнительный вопрос:

Как я могу обработать этот другой оригинал для ожидаемого.

 //Another original array.
var arr2 = [ 
  { name: 'a', version: '0.1', count: 1 },
  { name: 'b', version: '216', count: 1 },
  { name: 'b', version: '209', count: 1 },
  { name: 'b', version: '216', count: 1 },
  { name: 'b', version: '216', count: 1 },
  { name: 'b', version: '213', count: 1 },
  { name: 'b', version: '213', count: 1 },
  { name: 'b', version: '209', count: 1 },
  { name: 'b', version: '216', count: 1 },
  { name: 'b', version: '216', count: 1 }
];

//expected output
// { name: 'a', version: '0.1', count: 1 },
// { name: 'b', version: '216', count: 5 },
// { name: 'b', version: '209', count: 2 },
// { name: 'b', version: '213', count: 2 }
 

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

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

2. Каково ваше определение более высокой версии, когда значение версии непредсказуемо?

3. выполняемый фрагмент и консоль. журнал может помочь

4. Ваш ожидаемый результат [3,4] никоим образом не соответствует правилам, изложенным вами выше. Пожалуйста, объясните, как этот вывод / код вообще связан с изложенными вами правилами.

5. @Kienht Просто сравните версии, так как ascii достаточно!

Ответ №1:

Вы можете использовать Array#reduce с объектом для хранения объекта для каждого имени.

 var arr = [
  {'name': 'b', 'version': '103', 'count': 10}, 
  {'name': 'a', 'version': '0.1b', 'count': 73}, 
  {'name': 'b', 'version': '109', 'count': 67}, 
  {'name': 'a', 'version': '1.0.3', 'count': 100}, 
  {'name': 'a', 'version': '2.1.0', 'count': 100}, 
  {'name': 'c', 'version': 'a103', 'count': 30}, 
  {'name': 'c', 'version': 'a111', 'count': 100}
];
const res = Object.values(arr.reduce((acc,{name, version, count})=>{
  if(!acc[name] || acc[name] amp;amp; 
          (acc[name].count < count 
           || acc[name].count === count amp;amp; acc[name].version < version)){
    acc[name] = {name, version, count};
  }
  return acc;
}, {}));
console.log(res); 

Ответ №2:

Похоже, что во втором случае вы хотите объединить count свойство для записей с одинаковыми name и version (аналогично COUNT GROUP BY запросам в SQL базах данных).

В этом случае вы могли бы сначала вычислить dictionary_res индексированный by name на первом уровне и by version на втором уровне:

 dictionary_res = arr2.reduce((acc, { name, version, count }) => {
  if (!acc[name] || (acc[name] amp;amp; !acc[name][version])) {
    acc[name] = acc[name] || {}
    acc[name][version] = { count: count }
  } else {
    acc[name][version]['count'] = acc[name][version]['count']   count
  }
  return acc
}, {})
 

dictionary_res выдает значение, очень близкое к желаемому:

 {
  a: { '0.1': { count: 1 } },
  b:
  { '209': { count: 2 }, '213': { count: 2 }, '216': { count: 5 } }
}
 

Тем не менее, вам все равно нужно превратить это в массив, чтобы полностью достичь желаемого:

 array_res = Object.keys(dictionary_res).reduce((acc, name) => {
  Object.keys(dictionary_res[name]).forEach((version) => (
    acc.push({ name, version, count: dictionary_res[name][version]['count'] })
  ))
  return acc
}, [])
 

array_res теперь выдает ожидаемое значение:

 [ { name: 'a', version: '0.1', count: 1 },
  { name: 'b', version: '209', count: 2 },
  { name: 'b', version: '213', count: 2 },
  { name: 'b', version: '216', count: 5 } ]
 

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

1. Превосходно! На самом деле, мне нужно ввести результат второго случая (ваш ответ) в первый. Спасибо.