TransWikia.com

javascript: разбить массив на массивы по 1 букве элемента массива

Stack Overflow на русском Asked by Zhihar on January 11, 2021

Подскажите как получше реализовать следующую задачу:

Есть массив элементов, которые содержат поля value. Необходимо получить массив, содержащий массивы элементов у которых все поля начинаются с одинаковой буквы (одинакового символа).

Поскольку массив не большой и скорость не очень критична, то можно использовать и не очень оптимальные, зато понятные и компактные техники.

Делаю так:

// отсортировать входной массив
const sorted = this.props.data.sort((a, b) => a.value.localeCompare(b.value));

// получить список уникальных первых букв
const letters = sorted.map(obj => obj.value[0].toUpperCase()).sort().filter(function(item, pos, data) {
    return !pos || item !== data[pos - 1];
});

// сформировать итоговый массив
const lists = letters.map(obj => sorted.filter(item => obj.localeCompare(item.value[0]) === 0));

(предложенный код конечно в 1 строчку записать можно было бы, но разбил для удобства)

Подскажите, можно ли более толково сделать?
Т.е.

  1. улучшение производительности при сохранении компактности записи и понятности кода
  2. улучшение понятности кода
  3. улучшение компактности кода при сохранении понятности кода

Например мне очень не нравится как реализована уникальность букв в массиве – через

.filter(function(item, pos, data) {
        return !pos || item !== data[pos - 1];
    });

Может есть более правильный путь?

P.S.

входные данные

data = [
    {value = "Иван", id = 11},
    {value = "Игорь", id = 10},
    {value = "Михаил", id = 18},
    {value = "Максим", id = 21},
    {value = "Петр Викторович", id = 110},
];

2 Answers

такое что ли?

const data = [
    {value : "Иван", id : 11},
    {value : "Игорь", id : 10},
    {value : "Михаил", id : 18},
    {value : "Максим", id : 21},
    {value : "Петр Викторович", id : 110},
];

let group = data.reduce(function(acc,v){ 
                       let l = v.value[0].toUpperCase();
                       if(!acc[l]) acc[l] = [];
                       acc[l].push(v);                       
                       return acc;
                   }, { });

let result = Object.values(group);
console.log(result);

Correct answer by teran on January 11, 2021

const sorted = this.props.data.sort(); — эта строчка не делает то, что задумывалось: sort() по умолчанию сортирует по алфавиту, а у вас в data лежат объекты.

Можно еще так:

let data = [
  { value: "Иван", id: 11 },
  { value: "Игорь", id: 10 },
  { value: "Михаил", id: 18 },
  { value: "Максим", id: 21 },
  { value: "Петр Викторович", id: 110 },
];


data.sort((obj1, obj2) => obj1.value < obj2.value ? -1 : 1);

let curr_inner = [ data[0] ], result = [ curr_inner ];

for (let i = 1; i < data.length; i++) {
  if (data[i].value[0] != data[i - 1].value[0]) { // Первые буквы не равны?
    result.push(curr_inner = []); // Создается новый массив, добавляется в result
  } // curr начинает ссылаться на этот массив, элементы продолжат добавляться туда
  
  curr_inner.push(data[i]);
}

console.log(result);

И, например, завернуть это дело в функцию, оставив у неё вверху комментарий, описывающий, что она делает.

Answered by OPTIMUS PRIME on January 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP