Adriano Bellavita
Adriano Bellavita

Reputation: 141

React native: group array items to build a section list

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!

Upvotes: -3

Views: 774

Answers (4)

Faizan Ali
Faizan Ali

Reputation: 47

function makeResponse(obj) {
  const map = {};
  const finalArr = [];

  obj.movies.map((item) => {
    const { releaseYear, ...rest } = item;

    if (!map[item.releaseYear]) {
      map[item.releaseYear] = true;
      finalArr.push({ releaseYear, data: [rest] });
    } else {
      const index = finalArr.findIndex(
        (i) => i.releaseYear === item.releaseYear
      );

      finalArr[index] = {
        releaseYear: finalArr[index].releaseYear,
        data: [...finalArr[index].data, rest],
      };
    }
  });

  return finalArr;
}

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

makeResponse(obj);

Upvotes: 0

Terry Lennox
Terry Lennox

Reputation: 30725

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

Upvotes: 0

Disco
Disco

Reputation: 1634

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

Upvotes: 0

Layhout
Layhout

Reputation: 1590

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

Upvotes: 0

Related Questions