Улучшить базу деления массива по его элементу

Я хочу разделить массив на два массива на основе его элементов например, если у меня есть этот массив в качестве ввода

[{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 массивов, что не очень хорошо для производительности.

Есть ли способ сделать все это в одном цикле?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
48
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Пройдитесь по массиву только один раз, используйте критерии, чтобы решить, в какой массив следует поместить элемент. Например:

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;
  }, []);
}

Спасибо это именно то, что я хочу

Neji Soltani 30.05.2018 12:37

Вы можете зацикливаться только один раз, используя 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"
    }
  ]
}"

это оптимальный способ. Теперь вы конвертируете этот код, используя методы декларативного программирования, такие как сокращение, фильтр или что-то еще, что вам нравится.

Ronn Wilder 30.05.2018 12:41

Другие вопросы по теме