Отображение уникальных инициалов в списке

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я хочу написать уникальные инициалы перед перечислением массива имен, поэтому, учитывая const names = [«Билл», «Джек», «Джон»], я хотел бы напечатать что-то вроде:

 <ul>
    <li>B
        <ul>
            <li>Bill</li>
        </ul>
    </li>
    <li>J
        <ul>
            <li>John</li>
            <li>jack</li>
        </ul>
    </li>
</ul>
 

Способ, который я нашел для этого, — поместить JSX в массив, прежде чем отображать его как:

     const RenderNames = () => {
        let initials = [];
        let renderData = [];
        names.forEach(name => {
            let initial = name.charAt(0).toUpperCase();
            if(initials.indexOf(initial) === -1){
                initials.push(initial)
                renderData.push(<li>{initial}</li>)
            }
            renderData.push(<li>{name}</li>)
        });
        return <ul>{renderData}</ul>;
    }
 

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

Комментарии:

1. На самом деле это больше Javascript , чем React вопрос.

Ответ №1:

Поехали:

 const names = ['Bill', 'Jack', 'john', 'Alex'];
const groupedNames = names.reduce((accumulator, name) => {
    // first char of name, uppercased
    const firstLetter = name[0].toUpperCase();

    // check if data for key exist
    const namesList = accumulator[firstLetter] || [];

    // check if name in array exist to prevent duplicates
    // keep in mind for example John and john are not the same
    if (!namesList.includes(name)) {
        namesList.push(name);
    }

    // collect data and return
    return {...accumulator, [firstLetter]: namesList}
}, {});

 

и результат

 { B: [ 'Bill' ], J: [ 'Jack', 'john' ], A: [ 'Alex' ] }
 

Затем вы можете сортировать ключи и map() по ним.

Ответ №2:

Вы можете использовать это::

 const names = ['Bill', 'John', 'bob', 'Jack'];
    const category = names.reduce((unique, name) => {
        const char = name.charAt(0).toUpperCase();
        return (unique[char] ? { ...unique, [char]: [...unique[char], name] } : { ...unique, [char]: [name] });
    }, {});
    return (
        <div className="App">
            <ul>
                {
                    Object.entries(category).map(([key, value]) =>
                        <ul>
                            <li>{key}</li>
                            {
                                value.length amp;amp;
                                <ul>
                                    {
                                        value.map(name =>
                                            <li>{name}</li>
                                        )
                                    }
                                </ul>
                            }
                        </ul>
                    )}
            </ul>
        </div>
    );
 

Проверьте эту ссылку:

https://codesandbox.io/s/vigilant-sound-ukv0q?file=/src/App.js

Комментарии:

1. При этом печатаются инициалы с повторением, а не имена.

2. Я отредактировал свой ответ

3. Потрясающе! Спасибо за помощь 🙂

4. Пожалуйста. Я только что получил благодарность