Let's say there is an object that looks like this:
Data object
const movies = {
action: {
actionMovie1: {
title: "Action Movie 1", // <-- Move to the separate object
rating: 5,
},
actionMovie2: {
title: "Action Movie 2", // <-- Move to the separate object
rating: 5,
},
actionMovie3: {
title: "Action Movie 3", // <-- Move to the separate object
rating: 5,
},
},
adventure: {
adventureMovie1: {
title: "Adventure Movie 1", // <-- Move to the separate object
rating: 5,
},
adventureMovie2: {
title: "Adventure Movie 2", // <-- Move to the separate object
rating: 5,
},
adventureMovie3: {
title: "Adventure Movie 3", // <-- Move to the separate object
rating: 5,
},
},
animated: {
new: {
newAnimatedMovie1: {
title: "New Animated Movie 1", // <-- Move to the separate object
rating: 5,
},
newAnimatedMovie2: {
title: "New Animated Movie 2", // <-- Move to the separate object
rating: 5,
},
},
reviewed: {
reviewedAnimatedMovie1: {
title: "Reviewed Animated Movie 1", // <-- Move to the separate object
rating: 5,
},
reviewedAnimatedMovie2: {
title: "Reviewed Animated Movie 2", // <-- Move to the separate object
rating: 5,
},
},
},
};
Now I'm trying to iterate a data object, collect all the movie titles and put them in a separate object so that the final result looks something like this:
Expected result
const movieTitles = {
actionMovie1: "Action Movie 1",
actionMovie2: "Action Movie 2",
actionMovie3: "Action Movie 3",
adventureMovie1: "Adventure Movie 1",
adventureMovie2: "Adventure Movie 2",
adventureMovie3: "Adventure Movie 3",
newAnimatedMovie1: "New Animated Movie 1",
newAnimatedMovie2: "New Animated Movie 2",
reviewedAnimatedMovie1: "Reviewed Animated Movie 1",
reviewedAnimatedMovie2: "Reviewed Animated Movie 2",
};
So far, the closest result I could get was with this method, but it only works for the first two keys.
Current attempt
const movieTitles = Object.fromEntries(
Object.values(movies).flatMap((movie) =>
Object.entries(movie).map(([key, value]) => [key, value.title])
)
);
Could you please help complete this function, given the fact that more data may be added in the future. For example, later the data object might look like this:
Updated data object
const movies = {
action: {
actionMovie1: {
title: "Action Movie 1",
rating: 5,
},
actionMovie2: {
title: "Action Movie 2",
rating: 5,
},
actionMovie3: {
title: "Action Movie 3",
rating: 5,
},
actionMovie4: { // <-- New, follows the same structure
title: "Action Movie 4",
rating: 5,
},
},
adventure: {
adventureMovie1: {
title: "Adventure Movie 1",
rating: 5,
},
adventureMovie2: {
title: "Adventure Movie 2",
rating: 5,
},
adventureMovie3: {
title: "Adventure Movie 3",
rating: 5,
},
adventureMovie4: { // <-- New, follows the same structure
title: "Adventure Movie 4",
rating: 5,
},
},
animated: {
new: {
newAnimatedMovie1: {
title: "New Animated Movie 1",
rating: 5,
},
newAnimatedMovie2: {
title: "New Animated Movie 2",
rating: 5,
},
newAnimatedMovie3: { // <-- New, follows the same structure
title: "New Animated Movie 3",
rating: 5,
},
},
reviewed: {
reviewedAnimatedMovie1: {
title: "Reviewed Animated Movie 1",
rating: 5,
},
reviewedAnimatedMovie2: {
title: "Reviewed Animated Movie 2",
rating: 5,
},
reviewedAnimatedMovie3: { // <-- New, follows the same structure
title: "Reviewed Animated Movie 3",
rating: 5,
},
},
translated: { // <-- New category, follows the same structure
translatedAnimatedMovie1: { // <-- New, follows the same structure
title: "Translated Animated Movie 1",
rating: 5,
},
},
},
};
New expected result
const movieTitles = {
actionMovie1: "Action Movie 1",
actionMovie2: "Action Movie 2",
actionMovie3: "Action Movie 3",
actionMovie4: "Action Movie 4",
adventureMovie1: "Adventure Movie 1",
adventureMovie2: "Adventure Movie 2",
adventureMovie3: "Adventure Movie 3",
adventureMovie4: "Adventure Movie 4",
newAnimatedMovie1: "New Animated Movie 1",
newAnimatedMovie2: "New Animated Movie 2",
newAnimatedMovie3: "New Animated Movie 3",
reviewedAnimatedMovie1: "Reviewed Animated Movie 1",
reviewedAnimatedMovie2: "Reviewed Animated Movie 2",
reviewedAnimatedMovie3: "Reviewed Animated Movie 3",
translatedAnimatedMovie1: "Translated Animated Movie 1",
};
CodePudding user response:
If you don't know what sort of possible categories there'll be, it looks like you'll need to check, when iterating over an object, whether it has a title
property - and if not, then it's a new category, rather than a movie, and so you need to iterate over the whole category.
While this is possible by returning an array of entries to turn into an object, while not flattening quite all the way to keep the entry arrays, I think a more imperative recursive function would make more sense.
const movies={action:{actionMovie1:{title:"Action Movie 1",rating:5},actionMovie2:{title:"Action Movie 2",rating:5},actionMovie3:{title:"Action Movie 3",rating:5},actionMovie4:{title:"Action Movie 4",rating:5}},adventure:{adventureMovie1:{title:"Adventure Movie 1",rating:5},adventureMovie2:{title:"Adventure Movie 2",rating:5},adventureMovie3:{title:"Adventure Movie 3",rating:5},adventureMovie4:{title:"Adventure Movie 4",rating:5}},animated:{new:{newAnimatedMovie1:{title:"New Animated Movie 1",rating:5},newAnimatedMovie2:{title:"New Animated Movie 2",rating:5},newAnimatedMovie3:{title:"New Animated Movie 3",rating:5}},reviewed:{reviewedAnimatedMovie1:{title:"Reviewed Animated Movie 1",rating:5},reviewedAnimatedMovie2:{title:"Reviewed Animated Movie 2",rating:5},reviewedAnimatedMovie3:{title:"Reviewed Animated Movie 3",rating:5}},translated:{translatedAnimatedMovie1:{title:"Translated Animated Movie 1",rating:5}}}};
const movieTitles = {};
const getTitles = (parent) => {
for (const [key, value] of Object.entries(parent)) {
if (value.title) {
movieTitles[key] = value.title;
} else {
getTitles(value);
}
}
};
getTitles(movies);
console.log(movieTitles);