Given an array that nests inner objects which have key-value pairs, I want to convert single-element-arrays to just the value itself.
So let's say that we have the following albums
array:
const albums = [
{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": [ "coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
]
Since all the arrays are single-values, I would like to convert this entire albums
object to:
// desired output
[
{
"band": "beetles",
"album": "yellow_submarine",
"year": 1969
},
{
"band": "coldplay",
"album": "Parachutes",
"year": 2000
},
{
"band": "nirvana",
"album": "nevermind",
"year": 1991
}
]
I've seem lots of posts discussing the opposite (i.e., how to convert a single value into an array), but could not find an answer to this current question. Maybe I'm not using the correct search terms...
CodePudding user response:
If you want to create a new array of new objects, you'd use map
along with creating new objects unwrapping their values. You have a couple of options for how to handle the objects. You could use Object.fromEntries
and Object.entries
:
const updatedAlbums = albums.map(album =>
Object.fromEntries(
Object.entries(album).map(([key, value]) => [key, value[0]])
)
);
Live Example:
const albums = [
{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": [ "coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
];
const updatedAlbums = albums.map(album =>
Object.fromEntries(
Object.entries(album).map(([key, value]) => [key, value[0]])
)
);
console.log(updatedAlbums);
.as-console-wrapper {
max-height: 100% !important;
}
Or you could use an inner loop to avoid intermediary arrays:
const updatedAlbums = albums.map(album => {
const newAlbum = {};
for (const key in album) {
if (Object.hasOwn(album, key)) {
newAlbum[key] = album[key][0]; // Unwrapping the value
}
}
return newAlbum;
});
Live Example:
const albums = [
{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": [ "coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
];
// Quick-and-dirty polyfill for environments that don't have `Object.hasOwn` yet
if (!Object.hasOwn) {
Object.hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
}
const updatedAlbums = albums.map(album => {
const newAlbum = {};
for (const key in album) {
if (Object.hasOwn(album, key)) {
newAlbum[key] = album[key][0]; // Unwrapping the value
}
}
return newAlbum;
});
console.log(updatedAlbums);
.as-console-wrapper {
max-height: 100% !important;
}
CodePudding user response:
Map albums
to a new array of objects, use a unArray
method within the map
-lambda
const albums = [{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": ["coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
];
// Note: for a true copy of albums and its arrays,
// the values must be spreaded (e.g. ...album.band)
const noArrays = albums.map(album => {
const unArray = v => v.length === 1 ? v.shift() : v;
return { ...{},
band: unArray(...album.band),
album: unArray(...album.album),
year: unArray(...album.year)
};
});
console.log(noArrays);
.as-console-wrapper {
max-height: 100% !important;
}
If the keys of the albums
entries are not (all) known, using a reducer for all album
entries would be more generic:
const albums = [{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": ["coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
];
// Note: for a true copy of albums and its arrays,
// the values ust be spreaded (i.e ...value)
const noArrays = albums.map( album => {
const unArray = v => v.length === 1 ? v.shift() : v;
return Object.entries(album).reduce( (acc, [key, value]) =>
({...acc, [key]: unArray(...value)}), {});
});
console.log(noArrays);
CodePudding user response:
Edit: This changes the value in place rather than creating a new dictionary with the final result.
for (var i = 0; i < albums.length; i ) {
for (var key in albums[i]) {
albums[i][key] = albums[i][key][0];
}
}
CodePudding user response:
Keep it Simple! You can achieve this by just using Array.toString() method.
Working Demo :
const albums = [
{
"band": ["beetles"],
"album": ["yellow_submarine"],
"year": [1969]
},
{
"band": [ "coldplay"],
"album": ["Parachutes"],
"year": [2000]
},
{
"band": ["nirvana"],
"album": ["nevermind"],
"year": [1991]
}
];
albums.forEach((obj) => {
Object.keys(obj).forEach((key) => {
obj[key] = obj[key].length === 1 ? obj[key].toString() : obj[key]
});
});
console.log(albums);