#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. Превосходно! На самом деле, мне нужно ввести результат второго случая (ваш ответ) в первый. Спасибо.