Flatten arrays within object of arrays with data from parent object

Viewed 54

I want to flatten some arrays nested in each object of an array of objects to return an array of objects with data from the parent objects. Quite a mouthful but perhaps some example json will help explain.

My current data and code is:

const galleries = [
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
            },
            {
                "url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
            },
            {
                "url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
            }
        ],
        "slug": "stella-mccartney",
        "title": "Stella McCartney"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
            },
            {
                "url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
            }
        ],
        "slug": "esquire",
        "title": "Esquire"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
            },
            {
                "url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
            }
        ],
        "slug": "matches",
        "title": "Matches"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
            }
        ],
        "slug": "testing-project-2",
        "title": "Testing Project 2"
    }
]

const AllThumbnails = [].concat(
        ...galleries.map((gallery) => ({
            image: gallery.gallery,
            slug: gallery.slug,
        }))
    )
    
    console.log(AllThumbnails)

My ideal output is:

[
    {
        "url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg",
        "slug": "stella-mccartney"
    },
    {
        "url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg",
        "slug": "stella-mccartney"
    },
    {
        "url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg",
        "slug": "stella-mccartney"
    },
    {
        "url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg",
        "slug": "esquire"
    },
    {
        "url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg",
        "slug": "esquire"
    },
    {
        "url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg",
        "slug": "matches"
    },
    {
        "url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg",
        "slug": "matches"
    },
    {
        "url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg",
        "slug": "testing-project-2",
    }
]

How can I append the slug property correctly? Any help/pointers would be much appreciated.

4 Answers

you can use reduce to do this

const galleries = [{
    "gallery": [{
        "url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
      },
      {
        "url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
      },
      {
        "url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
      }
    ],
    "slug": "stella-mccartney",
    "title": "Stella McCartney"
  },
  {
    "gallery": [{
        "url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
      },
      {
        "url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
      }
    ],
    "slug": "esquire",
    "title": "Esquire"
  },
  {
    "gallery": [{
        "url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
      },
      {
        "url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
      }
    ],
    "slug": "matches",
    "title": "Matches"
  },
  {
    "gallery": [{
      "url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
    }],
    "slug": "testing-project-2",
    "title": "Testing Project 2"
  }
]

const flatten = galleries.reduce((acc, curr) => {
  curr.gallery.forEach(g => {
    acc.push({
      url: g.url,
      slug: curr.slug
    });
  });
  return acc;
}, []);

console.log(flatten);

You could use

const allThumbnails = galleries.map(parent => 
    parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();

.map() will map each parent object to an array of {url, slug}, and then .flat() will flatten these nested arrays.

const galleries = [
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
            },
            {
                "url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
            },
            {
                "url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
            }
        ],
        "slug": "stella-mccartney",
        "title": "Stella McCartney"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
            },
            {
                "url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
            }
        ],
        "slug": "esquire",
        "title": "Esquire"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
            },
            {
                "url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
            }
        ],
        "slug": "matches",
        "title": "Matches"
    },
    {
        "gallery": [
            {
                "url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
            }
        ],
        "slug": "testing-project-2",
        "title": "Testing Project 2"
    }
];

const allThumbnails = galleries.map(parent => parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();
    
console.log(allThumbnails);

Looks like I'm a little late with my answer, I think Kirill's solution is going to be the most practical one. Here is my solution anyways:

let newArray = []
galleries.forEach(function (gallery) {
    gallery["gallery"].forEach(function (url) {
         newArray.push({"url": url["url"], "slug": gallery["slug"]})
     })
})

Some of these answers are very close to mine, but here's mine using forEach with ES6 syntax, which in my opinion is more readable:

const allThumbnails = new Array();

thumbnails.forEach(set => {
    set.galleries.forEach(item => {
        allThumbnails.push({url: item.url, slug: set.slug};
    });
});
Related