Reputation: 4614
I got stuck while working on a function that should return an array of objects from another array of objects. As can be seen below, I use only one key and return a "simple" array instead of an array of objects:
function pluck(array, key) {
return array.map(x => x[key]);
}
var myArr = [{
name: "United Kingdom",
alpha3: "GBR",
code: "GB",
region: "Europe",
tax: 5,
status: 1
}, {
name: "Romania",
alpha3: "ROM",
code: "RO",
region: "Europe",
tax: 3,
status: 1
}];
myArr = pluck(myArr, 'name');
console.log(myArr);
If I use 2 (or more) keys, I still get a "simple" array of values corresponding to the last key used:
function pluck(array, key1, key2) {
return array.map(x => x[key1, key2]);
}
var myArr = [{
name: "United Kingdom",
alpha3: "GBR",
code: "GB",
region: "Europe",
tax: 5,
status: 1
}, {
name: "Romania",
alpha3: "ROM",
code: "RO",
region: "Europe",
tax: 3,
status: 1
}];
myArr = pluck(myArr, 'name', 'code');
console.log(myArr);
What I want is:
var myArr = [
{name: "United Kingdom", code: "GB"},
{name: "Romania", code: "RO"}
]
What is missing?
Upvotes: 1
Views: 163
Reputation: 29012
x[key1, key2]
won't do what you want, because key1, key2
will evaluate to key2
(since it would use the comma operator).
Plus, you are currently creating an array with just the values, not with objects that contain the relevant keys and values.
You can use the way TKoL showed for 2 keys, or you could generalize it into a function that can take any number of keys:
function pluck (array, ...keys) {
return array.map(x =>
keys.reduce((obj, key) =>
Object.assign(obj, { [key]: x[key] }),
{})
)
}
var myArr = [{
name: "United Kingdom",
alpha3: "GBR",
code: "GB",
region: "Europe",
tax: 5,
status: 1
}, {
name: "Romania",
alpha3: "ROM",
code: "RO",
region: "Europe",
tax: 3,
status: 1
}];
myArr = pluck(myArr, 'name', 'code');
console.log(myArr);
This uses ...keys
to define keys
as a rest argument that contains all the remaining arguments as an array. Later we iterate over this array of keys
to assemble the desired object for each element: reduce
is called with {}
as initial value, and for every iteration it adds one of the keys to the object and returns the final object at the end. Object.assign(obj, { [key]: x[key] })
is used instead of { ...obj, [key]: x[key] }
to avoid unnecessary creation of a new object every time.
An alternative, more imperative way of writing this function would be using a for
loop:
function pluck (array, ...keys) {
return array.map(x => {
const obj = {}
for (const key of keys) {
obj[key] = x[key]
}
return obj
})
}
Upvotes: 4
Reputation: 13892
function pluck(array, key1, key2) {
return array.map(x => ({
[key1]: x[key1],
[key2]: x[key2]
}));
}
var myArr = [{
name: "United Kingdom",
alpha3: "GBR",
code: "GB",
region: "Europe",
tax: 5,
status: 1
}, {
name: "Romania",
alpha3: "ROM",
code: "RO",
region: "Europe",
tax: 3,
status: 1
}];
myArr = pluck(myArr, 'name', 'code');
console.log(myArr);
Seems like you meant to do something like that. You could make it more generalized by the second parameter being an array of keys, and inside the map function iterating over each key and adding it to the object one by one.
Upvotes: 5