Home > other >  Render unique initials in a list
Render unique initials in a list

Time:12-08

I want to write unique initials before listing an array of names, so given const names = ["Bill", "Jack", "john"], I would like to print something like:

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

The way I found to do this is to push the JSX into an array before rendering it like:

    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>;
    }

But I feel the code is a bit clunky, and I can only push in tags that are immediately closing. Is this the best way to do things or could it be done better?

CodePudding user response:

Here we go:

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

and result is

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

Then you can sort keys and map() over it.

CodePudding user response:

You can use this::

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 &&
                                <ul>
                                    {
                                        value.map(name =>
                                            <li>{name}</li>
                                        )
                                    }
                                </ul>
                            }
                        </ul>
                    )}
            </ul>
        </div>
    );

Check this link:

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

  • Related