What would be the "correct" way of transforming an array of objects into an object that contains an array?
Suppose I have this array that contains objects:
const paintings = [
{ painting: "Mona Lisa" },
{ painting: "The Starry Night" },
{ painting: "The Last Supper" },
{ painting: "Girl with a Pearl Earring" },
{ painting: "American Gothic" },
{ painting: "The Night Watch" }
];
And I would like to transform it into this:
const paintings = {
artworks: [
"Mona Lisa",
"The Starry Night",
"The Last Supper",
"Girl with a Pearl Earring",
"American Gothic",
"The Night Watch"
]
};
I know that I can accomplish this with two nested loops like below, but is there a more "elegant" way of doing it? I think that these tasks are nowadays usually solved using map or reduce functions but I find them a bit confusing to use. I would like to learn though!
const paintingsNew = {
artworks: []
};
for (const painting of paintings) {
for (const val of Object.values(painting).values()) {
paintingsNew.artworks.push(val);
}
}
console.log(paintingsNew);
// { artworks:
// [ 'Mona Lisa',
// 'The Starry Night',
// 'The Last Supper',
// 'Girl with a Pearl Earring',
// 'American Gothic',
// 'The Night Watch' ] }
2 Answers 2
Your code flattens the entire array of {} objects, indiscriminately flattening all properties. It does not mind, if there is only one single property, but it does not make sense semantically, especially if the array is named paintings
.
Rather consider the resulting array a projection/mapping to a single property painting
.
For a consistent array check and take only the painting
property.
for (const p of paintings) {
if ("painting" in p) {
paintingsNew.artworks.push(p.painting);
}
}
The extra if
protects against undefined
entering corrupted data.
If you want to use Array.prototype.map
you can write something like this:
const paintings = [
{ painting: "Mona Lisa" },
{ painting: "The Starry Night" },
{ painting: "The Last Supper" },
{ painting: "Girl with a Pearl Earring" },
{ painting: "American Gothic" },
{ painting: "The Night Watch" }
];
const paintingsNew = {
artworks: []
};
paintings.map(x => {
paintingsNew.artworks.push(x);
});
When you use map
it practically iterates over every item of the array. We have to pass a callback function accepting the currentValue
(here the x
argument), and optionally the index
and the array
.
You can (and normally should) return some calculated value in the callback function. Since here everything you want is to create a new object containing the array, you push each item to the array inside the object paintingsNew
. You don't even need map
for this, you can just write:
const paintingsNew = {
artworks: paintings // paintings is defined before
};
However I suppose you'd have some further requirements, which you could work out inside the callback function of the map
. As suggested by @Joop Eggen, you could check if the key painting
is present in the object:
paintings.map(x => {
if ('painting' in x) {
paintingsNew.artworks.push(x);
}
});
Now this would make more sense when using map
. You could certainly apply some more advanced logic if your initial array is more diverse and you'd like to create an output object with more complex structure.
EDIT: Immediatelly after posting I saw you want to get only the value for the key painting
. This means in the map
callback you push x.painting
instead of just x
.
paintings.map(x => {
if ('painting' in x) {
paintingsNew.artworks.push(x.painting);
}
});
-
6\$\begingroup\$ You are misusing
map
. It is for creating a new array like this:const newPaintings = paintings.map(x => x.painting)
, not to execute side-effects. You should be using.forEach()
. \$\endgroup\$RoToRa– RoToRa2020年01月29日 14:41:05 +00:00Commented Jan 29, 2020 at 14:41 -
1\$\begingroup\$ @RoToRa thank you for the comment. You're right,
.forEach()
is more appropriate for this. I used.map()
because the OP stated in the question he/she wanted to usemap
orreduce
. \$\endgroup\$cezar– cezar2020年01月29日 14:43:57 +00:00Commented Jan 29, 2020 at 14:43 -
artworks
maps every{painting:"MonaLisa", artist: ...}
to itspainting
. In Computer Science a projection. \$\endgroup\$