javascript: разбить массив на массивы по 1 букве элемента массива
Подскажите как получше реализовать следующую задачу:
Есть массив элементов, которые содержат поля 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 строчку записать можно было бы, но разбил для удобства)
Подскажите, можно ли более толково сделать? Т.е.
- улучшение производительности при сохранении компактности записи и понятности кода
- улучшение понятности кода
- улучшение компактности кода при сохранении понятности кода
Например мне очень не нравится как реализована уникальность букв в массиве - через
.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 шт):
такое что ли?
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);
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);
И, например, завернуть это дело в функцию, оставив у неё вверху комментарий, описывающий, что она делает.