Я хочу разделить массив на два массива на основе его элементов например, если у меня есть этот массив в качестве ввода
[{id:1,name:"item1_g1"},{id:2,name:"item2_g2"},{id:3,name:"item3_g1"},{id:2,name:"item4_g2"}]
на выходе должно быть два таких массива
первый массив:
[{id:1,name:"item1_g1"},{id:3,name:"item3_g1"}]
второй массив:
[{id:2,name:"item2_g2"},{id:2,name:"item4_g2"}]
Как и вам, мне просто нужно сгруппировать элементы на основе их атрибута name.
Я использую angularjs, и я уже пробовал этот код
var values = [{
id: 1,
name: "item1_g1"
}, {
id: 2,
name: "item2_g2"
}, {
id: 3,
name: "item3_g1"
}, {
id: 2,
name: "item4_g2"
}];
var group1 = values.filter(function(item) {
return (item.name.includes('g1'));
});
var group2 = values.filter(function(item) {
return (item.name.includes('g2'));
});
console.info(group1, group2)Но мне это решение не понравилось, потому что в случае, если у меня тяжелый массив, мне нужно зациклить его n раз, чтобы извлечь n массивов, что не очень хорошо для производительности.
Есть ли способ сделать все это в одном цикле?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Пройдитесь по массиву только один раз, используйте критерии, чтобы решить, в какой массив следует поместить элемент. Например:
var values = [
{ id: 1, name: "item1_g1" },
{ id: 2, name: "item2_g2" },
{ id: 3, name: "item3_g1" },
{ id: 2, name: "item4_g2" }
];
const [group1, group2] = values.reduce((groups, el) => {
groups[1^el.name.includes('g1')].push(el);
return groups;
}, [[], []]);
console.info(group1, group2);Вы можете создать более общую функцию группировки, которая принимает два аргумента - массив элементов для сортировки и функцию предиката (которая возвращает индекс). Это будет немного более многословно:
function groupBy(arr, indexer) {
return arr.reduce((groups, el) => {
const index = indexer(el);
groups[index] = groups[index] || [];
groups[index].push(el);
return groups;
}, []);
}
Вы можете зацикливаться только один раз, используя Array.prototype.reduce () в сочетании с String.prototype.slice ()
Пример кода:
const values = [{id: 1,name: "item1_g1"}, {id: 2,name: "item2_g2"}, {id: 3,name: "item3_g1"}, {id: 2,name: "item4_g2"}];
const groups = values.reduce((a, c) => (a[c.name.slice(-2)].push(c), a), {g1: [], g2: []});
console.info(groups);Вы можете сделать это за один цикл, как показано ниже:
var values = [{
id: 1,
name: "item1_g1"
}, {
id: 2,
name: "item2_g2"
}, {
id: 3,
name: "item3_g1"
}, {
id: 2,
name: "item4_g2"
}];
let group1 = [];
let group2 = [];
values.forEach( item => {
if (item.name.includes('g1')){
group1.push(item);
} else {
group2.push(item);
}
})
console.info(group1)
console.info(group2)
// I would do this the old fashioned way.
// iterate over values and add them to a map with same group id
// this way you won't need to worry about how many groups you have
var groups = {};
for(i=0;i<values.length;i++){
var groupNum = values[i].name.substring(values[i].name.indexOf('_g') + 2);
if (groups[groupNum]){
groups[groupNum].push(values[i]);
}
else {
groups[groupNum] = [values[i]];
}
}
console.info(groups);
{
"1": [
{
"id": 1,
"name": "item1_g1"
},
{
"id": 3,
"name": "item3_g1"
}
],
"2": [
{
"id": 2,
"name": "item2_g2"
},
{
"id": 2,
"name": "item4_g2"
}
]
}"
это оптимальный способ. Теперь вы конвертируете этот код, используя методы декларативного программирования, такие как сокращение, фильтр или что-то еще, что вам нравится.
Спасибо это именно то, что я хочу