Home > OS >  React native: group array items to build a section list
React native: group array items to build a section list

Time:12-13

I'd like to create a section list in react native, but I have to organize my REST API JSON response.

Here is my JSON

{
"movies": [
    { "id": "1", "title": "Star Wars", "releaseYear": "1990" },
    { "id": "2", "title": "Back to the Future", "releaseYear": "1990" },
    { "id": "3", "title": "The Matrix", "releaseYear": "2010" },
    { "id": "4", "title": "Inception", "releaseYear": "2010" },
    { "id": "5", "title": "Interstellar", "releaseYear": "2010" }
  ]
}

I'd like to obtain a structure like this

{
"movies": [
    
   {
     "releaseYear": "1990", "data": [
         { "id": "1", "title": "Star Wars"},
         { "id": "2", "title": "Back to the Future"}
      ] 
   },
   {
     "releaseYear": "2010", "data": [
         { "id": "3", "title": "The Matrix" },
         { "id": "4", "title": "Inception" },
         { "id": "5", "title": "Interstellar" }
      ] 
   }
}

If I use reduce, I cannot obtain the structure I'd like to have (this is because I just "group by" elements and I'm not able to move the "releaseYear" property and create new object array with filtered properties)

TY in advance!

CodePudding user response:

const movies = [
    { "id": "1", "title": "Star Wars", "releaseYear": "1990" },
    { "id": "2", "title": "Back to the Future", "releaseYear": "1990" },
    { "id": "3", "title": "The Matrix", "releaseYear": "2010" },
    { "id": "4", "title": "Inception", "releaseYear": "2010" },
    { "id": "5", "title": "Interstellar", "releaseYear": "2010" }
]

const result = movies.reduce((p, c) => {
    const found = p.findIndex(p => p.releaseYear === c.releaseYear);
    if (found !== -1) {
        p[found].data.push({ id: c.id, title: c.title });
    } else {
        p.push({ releaseYear: c.releaseYear, data: [{ id: c.id, title: c.title }] });
    }

    return p;
}, []);

console.log(result);

CodePudding user response:

Use a reducer, try to get the release year group and add the data to the array. If it does not exist add the release year and add the movie to the data array.

const movies = [
  { id: "1", title: "Star Wars", releaseYear: "1990" },
  { id: "2", title: "Back to the Future", releaseYear: "1990" },
  { id: "3", title: "The Matrix", releaseYear: "2010" },
  { id: "4", title: "Inception", releaseYear: "2010" },
  { id: "5", title: "Interstellar", releaseYear: "2010" },
];

// Map the movies by release year
const moviesByReleaseYear = movies.reduce((acc, movie) => {
  const { releaseYear, ...restOfMovie } = movie;
  const group = acc.find((item) => item.relseaseYear === releaseYear);
  if (!group) {
    acc.push({
      relseaseYear: releaseYear,
      data: [restOfMovie],
    });
  } else {
    group.data.push(restOfMovie);
  }
  return acc;
}, []);
console.log(moviesByReleaseYear);

CodePudding user response:

You can use Array.reduce() to group the movies by releaseYear, creating a data array for each year.

This creates an mapping object with a property for each year, we can then use Object.values() to get the result as an array.

We assign this to a movies property in the result object.

const input = {
  "movies": [
    { "id": "1", "title": "Star Wars", "releaseYear": "1990" },
    { "id": "2", "title": "Back to the Future", "releaseYear": "1990" },
    { "id": "3", "title": "The Matrix", "releaseYear": "2010" },
    { "id": "4", "title": "Inception", "releaseYear": "2010" },
    { "id": "5", "title": "Interstellar", "releaseYear": "2010" }
  ]
}

const result = { 
    movies: Object.values(input.movies.reduce((acc, { id, title, releaseYear }) => { 
      acc[releaseYear] = acc[releaseYear] || { releaseYear, data: [] };
      acc[releaseYear].data.push({ id, title });
      return acc;
    }, {}))
}

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

  • Related