0
<ol className={classes.ol}>
      {props.data.definitions
        .sort((a, b) => a.partOfSpeech.localeCompare(b.partOfSpeech))
        .map((definition, index) => {
          return (
            <>
              <h3>{definition.partOfSpeech}</h3>
              <li key={index} className={classes.list}>
                {definition.definition.charAt(0).toUpperCase() +
                  definition.definition.slice(1)}{" "}
                ({definition.partOfSpeech})
              </li>
            </>
          );
        })}
    </ol>

Above is the code that sorts 'partofSpeech' alphabetically and outputs a part of speech with definition of a word. I'm trying to have part of speech shown only once if part of speech is the same. The current output is shown below.

Is it possible to show part of speech only once at the top and render the list based on that part of speech? I've tried using reduce and comparing the object's partOfSpeech still wasn't able to achieve what I wanted.

This is a current output

What I'm trying to achieve:

What I am trying to achieve

Roma Kim
  • 321
  • 1
  • 8
  • You can group data based on "partofSpeech" using _.groupBy(props.data.definitions, def => def.partofSpeech); "groupBy" is a lodash function else you can use reduce to group as well. You can have a look on following answer: https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key – Hamza Khursheed Sep 28 '21 at 06:50

1 Answers1

1

Yes it's possible but you have to change your object that you try to map. Currently definition has the structure of

[{
  "definition": "located at or near the back of an animal",
  "partOfSpeech": "adjective"
}]

The structure you want for your case is something like:

[{
  "partOfSpeech": "adjective",
  "definitions": ["located at or near the back of an animal", "..."],  
}]
// or
[{
  "adjective": ["located at or near the back of an animal", "..."], 
  "adverb": ["in or to or toward a past time", "..."], 
}]

The "definitions" could also be an object inside an array but the key is that you need to group first by the properties and then have two iterators. One across partOfSpeech and within that one across "definitions"

You can build the grouping logic yourself with Array functions or use lodash groubBy

// groups by property length
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }

For more options how to group you can also look into How to group an array of objects by key

st.huber
  • 1,481
  • 2
  • 24
  • 45
  • Unfortunately, I will not be able to change the structure, since I'm getting this from an external API. – Roma Kim Sep 28 '21 at 07:10
  • 2
    You can still change it, because you call the API somewhere. You can then transform/change the response in anyway you like after fetching it. – st.huber Sep 28 '21 at 07:11
  • You can transform the response before assigning it to the react component's `props` – st.huber Sep 28 '21 at 07:12