Отсортируйте список по свойству и добавьте объект перед изменением каждой первой буквы в JavaScript

Итак, я пытаюсь создать такой интерфейс:

Отсортируйте список по свойству и добавьте объект перед изменением каждой первой буквы в JavaScript

И у меня есть множество пользователей

[{name: 'Julia'}, {name: 'Ismeh'}, {name: 'Alison'}, {name: 'Andrea'}, {name: 'Betty'}]

Я пытаюсь отсортировать массив по первой букве свойства name и добавить объект заголовка перед каждым. Например, на картинке вы можете увидеть буквы A, B, I и J в качестве заголовков.

На данный момент у меня это работает так:

    let final = []
    // sort by first letter
    const sortedUsers = state.test_list.sort((a, b) => a.name.localeCompare(b.name))
    for (let x = 0; x < sortedUsers.length; x++) {
        const user = sortedUsers[x].name
        if (user.charAt(0) === 'A') {
            const checkIfExists = final.findIndex((f) => f.header === 'A')
            // add the header A if it doesn't exist
            if (checkIfExists < 0) final.push({header: 'A'})
        }
        else if (user.charAt(0) === 'B') {
            const checkIfExists = final.findIndex((f) => f.header === 'B')
            // add the header B if it doesn't exist
            if (checkIfExists < 0) final.push({header: 'B'})
        }
        // else if up to the letter Z
        final.push(user)
    }

и если я зарегистрирую последний массив, я получу:

Отсортируйте список по свойству и добавьте объект перед изменением каждой первой буквы в JavaScript

что правильно.

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

Есть ли другой способ сделать что-то подобное? Любая помощь приветствуется.

Это для меня хорошее упражнение

Mario 27.03.2018 06:32
Поведение ключевого слова "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) для оценки ваших знаний,...
4
1
108
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Почему бы вам не создать коллекцию имен, сгруппированных по первой букве? Затем вы можете зациклиться на нем и создать свой список. Используйте Array#reduce для создания сгруппированной коллекции.

А затем используйте Object#keys, чтобы перебрать сгруппированную коллекцию и отобразить результаты:

let data = [{
  name: 'Julia'
}, {
  name: 'Ismeh'
}, {
  name: 'Alison'
}, {
  name: 'Andrea'
}, {
  name: 'Betty'
}];

let combined = data.reduce((result, item) => {
  let letter = item.name[0].toUpperCase();
  if (!result[letter]) {
    result[letter] = [];
  }

  result[letter].push(item);
  return result;
}, {});

console.info(combined);

// Iterate over the result
Object.keys(combined).forEach(key => {
  // key will be the first letter of the user names and
  // combined[key] will be an array of user objects
  console.info(key, combined[key]);
});

Еще нужно отсортировать пользовательские массивы по имени пользователя, что легко сделать с помощью Array#sort.

Потрясающие! Это то, что я искал.

wobsoriano 27.03.2018 06:02
Ответ принят как подходящий

Достаточно просто, попробуйте отсортировать их, а затем использовать .reduce:

const unsortedPeople = [{name: 'Julia'}, {name: 'Ismeh'}, {name: 'Alison'}, {name: 'Andrea'}, {name: 'Betty'}];
const sortedUsers = unsortedPeople.sort((a, b) => a.name.localeCompare(b.name))
const final = sortedUsers.reduce((finalSoFar, user) => {
  const thisUserFirstChar = user.name[0];
  if (finalSoFar.length === 0) addHeader();
  else {
    const lastUserFirstChar = finalSoFar[finalSoFar.length - 1].name[0];
    if (lastUserFirstChar !== thisUserFirstChar) addHeader();
  }
  finalSoFar.push(user);
  return finalSoFar;
  function addHeader() {
    finalSoFar.push({ header: thisUserFirstChar });
  }
}, []);

console.info(final);

Почему бы вам просто не отслеживать текущее сокращение в цикле. Затем вы можете добавить голову, когда она изменится:

var users = [{name: 'Julia'}, {name: 'Ismeh'}, {name: 'Alison'}, {name: 'Andrea'}, {name: 'Betty'}]

const sortedUsers = users.sort((a, b) => a.name.localeCompare(b.name))
var currentHeader 
let final = sortedUsers.reduce((a, user) => {
    if (currentHeader !==  user.name[0]) {
        currentHeader = user.name[0]
        a.push({header: currentHeader})
    }
    a.push(user)
    return a
},[])

console.info(final)

Это тоже выглядит потрясающе. Я тоже попробую это

wobsoriano 27.03.2018 06:13

Вот один из способов сделать это:

const users = [{name: 'Julia'}, {name: 'Ismeh'}, {name: 'Alison'}, {name: 'Andrea'}, {name: 'Betty'}];

let lastIndex;
let result = [];
users.sort((a, b) => {
  return a.name > b.name;
}).forEach((user) => {
  const index = user.name.charAt(0);
  if (index !== lastIndex) {
    result.push({
      header: index
    });
  }
  lastIndex = index;
  result.push(user.name);
}, []);






console.info(result);

Вы можете использовать метод lodash _.orderBy(collection, [iteratees=[_.identity]], [orders]) и _.groupBy(collection, [iteratee=_.identity]).

  • Этот Сортировать по похож на _.sortBy, за исключением того, что он позволяет указывать порядок сортировки итераций для сортировки. Если заказы не указаны, все значения сортируются в порядке возрастания. В противном случае укажите порядок «по убыванию» для сортировки по убыванию или «по возрастанию» для соответствующих значений.
  • группа по создаст объект, состоящий из ключей, сгенерированных в результате выполнения каждого элемента коллекции через итерацию. Порядок сгруппированных значений определяется порядком, в котором они встречаются в коллекции. Соответствующее значение каждого ключа представляет собой массив элементов, ответственных за генерацию ключа. Итерация вызывается с одним аргументом: (значение).

пример

// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }

// Sort by `user` in ascending order and by `age` in descending order.
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);

With lodash

let myArr = [{
  name: 'Julia'
}, {
  name: 'Ismeh'
}, {
  name: 'Andrea'
}, {
  name: 'Alison'
}, {
  name: 'Betty'
}];

myArr = _.orderBy(myArr, ['name'], ['asc']);

let r = _.groupBy(myArr, o => {
  return o.name.charAt(0).toUpperCase();
})

console.info(r);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

IN ES5

var arr = [{
    name: 'Julia'
  }, {
    name: 'Ismeh'
  }, {
    name: 'Andrea'
  }, {
    name: 'Alison'
  }, {
    name: 'Betty'
  }],
  fChar = '';
  
  
arr = arr.sort(function(a, b) {
  a = a.name.toUpperCase(); // ignore upper and lowercase
  b = b.name.toUpperCase(); // ignore upper and lowercase
  return a < b ? -1 : (a > b ? 1 : 0);
}).reduce(function(r, o) {
  fChar = o.name.charAt(0).toUpperCase();
  if (!r[fChar]) {
    r[fChar] = [];
  }
  r[fChar].push({
    name: o.name
  });
  return r;
}, {});

console.info(arr);

IN ES6

const arr = [{
    name: 'Julia'
}, {
    name: 'Ismeh'
}, {
    name: 'Andrea'
}, {
    name: 'Alison'
}, {
    name: 'Betty'
}];

let result = arr.sort((a, b) => {
    a = a.name.toUpperCase(); // ignore upper and lowercase
    b = b.name.toUpperCase(); // ignore upper and lowercase
    return a < b ? -1 : (a > b ? 1 : 0);
}).reduce((r, o) => {
    let fChar = o.name.charAt(0).toUpperCase();
    if (!r[fChar]) {
        r[fChar] = [];
    }
    r[fChar].push({
        name: o.name
    });
    return r;
}, {});

console.info(result);

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