1

I am new around here. Doing my first own project with React, I am stuck to achieve this. After mapping a list using .map(), how can I have multiple lists split? I want them to be split by the first letter on each new <ul>, regardless the number of titles. Some titles have more than 5 or 10, for each letter. Some are not even showed, because there are no titles with that letter.

My code

<ul>
    {list.map((i) => (
        <li>
           {i.title}
        </li>
    ))}
</ul>

Result

<ul>
  <li>title aa</li>
  <li>title ab</li>
  <li>title ac</li>
  <li>title ba</li>
  <li>title bb</li>
  <li>title bc</li>
  <li>title ca</li>
  <li>title cb</li>
  <li>title cc</li>
  …
</ul>

Desired

<ul>
  <li>title aa</li>
  <li>title ab</li>
  <li>title ac</li>
</ul>
<ul>
  <li>title ba</li>
  <li>title bb</li>
  <li>title bc</li>
</ul>
<ul>
  <li>title ca</li>
  <li>title cb</li>
  <li>title cc</li>
</ul>
  …

Thanks for any help and possible solution.

4
  • How would the items split? Commented Nov 11, 2021 at 16:36
  • I am receiving the data and it comes in alphabetic order. So I would like to split them by the first letter inside each new <ul>. Sorry I didn't make it clear in my question. I apologize for it. Thanks. Commented Nov 11, 2021 at 16:40
  • @Tamara you want to split it by 3 or on what condition do u want to split??. Commented Nov 11, 2021 at 16:43
  • Hi. I am sorry again. I'm gonna edit the question so I make it more clear. I want them to be split by the first letter, regardless the number on each of them. I am really sorry about it. I will fix the question. Commented Nov 11, 2021 at 16:47

2 Answers 2

2

You should reduce the list values following the desired pattern, then iterate over the sub-items one by one:

const grouped = list.reduce((acc, obj) => {
  const key = obj.title.charAt(6);
  acc[key] = acc[key] || [];
  acc[key].push(obj);
  return acc;
}, {});

which will lead grouped values as follows:

{
  a: [{
  title: "title aa"
}, {
  title: "title ab"
}],
  b: [{
  title: "title ba"
}, {
  title: "title bb"
}],
  c: [{
  title: "title ca"
}, {
  title: "title cb"
}]
}

You can then go through the grouped object and map to your proper layout:

Object.values(grouped).map(list => (
    <ul>
        {list.map((i) => (
            <li>
                {i.title}
            </li>
        ))}
    </ul>
});
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the help. I appreciate it. I tried to implement this, but I am getting an error. Says: TypeError: obj.charAt is not a function. Any idea why is that?
You should update the obj with obj.title. I am updating the answer.
It indeed worked out. Thanks ever so much. I've been stuck on this for 2 days. I really appreciate your time for helping me. Have a nice one!
Glad to be in help :)
0

It will depends on what is the condition to split your lists, but you can use reduce to generate a new list that will contains the splits that you need and then apply those splits to a new list.

function splitList(list) {
    return list.reduce((acc, cur) => {
        const lastSplit = acc[acc.length -1];
        if(lastSplit && lastSplit[0][0] === cur[0]) {
            return [...acc.slice(0, -1), [...lastSplit, cur]];
        } else {
            return [...acc, [cur]];
        }
    }, []);
}

After having your splits, you do the same thing you are doing for the li items, but for ul as well: (Replace the names of the variables)

{splitList(list).map(item) => (
    <ul>
        {item.map((i) => (
            <li>
            {i.title}
            </li>
        ))}
    </ul>
)}

5 Comments

Hi. Thanks for the help. I was able to implement that, but I still get all the items inside the single same <ul>. Would that be because of the splitList function? How can I change it to have it split by the first letter?
Take a look at this stackblitz with that code, you will see that it creates a new array with each new item. But I think the answer of tmarwen is better than mine, since it uses objects to store the values. stackblitz.com/edit/js-vpewnz?file=index.js
Indeed it is, as you mentioned. But when I console.log my I get the same result as it was first mapped. Nothing changed. I am giving a try with tmarwen's answer. Running into some issues. I hope I can find a way. Thanks for helping.
Hope you can find a solution to your issue. If you want to any another try, just post here.
I was able to make it work with tmarwen's answer. I appreciate also you trying to help me. Thanks ever so much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.