I am trying to find a shortcut or single line of code that can active following:
I have a array selectedFields
consisting of elements:
selectedFields = [ "time", "age", "city" ]
I have a object valueProvided
consisting of values:
valueProvided = { "time": "2022-10-01", "visa": "onArrival", "age": 30, "city": "paris", "hotel": "Holiday" }
I would like to compare the 2 fields and remove any elements from valueProvided object
that are not available in the array. Meaning in this case the elements visa
and hotel
are not present within selectedFields
so I would like to remove it from valueProvided
so my final result would look something like this:
result = { "time": "2022-10-01", "age": 30, "city": "paris" }
I am aware that I can loop over the elements in an array and remove the non-matching key from the object to achieve this, but I am trying to find if there is any shortcut or ES6 way of doing it in a single line or efficiently.
I found a couple of answers but in all cases, they are trying to compare the object with another object or array with another array but not the cross approach to compare an array with the object or vice versa.
CodePudding user response:
You can use Object.entries
to get the entries from valueProvided
, filter
them on whether the key is in selectedFields
, and then use Object.fromEntries
to build the result object:
const selectedFields = ["time", "age", "city"]
const valueProvided = {
"time": "2022-10-01",
"visa": "onArrival",
"age": 30,
"city": "paris",
"hotel": "Holiday"
}
const result = Object.fromEntries(
Object.entries(valueProvided).filter(([k, v]) => selectedFields.includes(k))
)
console.log(result)
As pointed out by @NickParsons in the comments, you can further optimise this (as long as all the keys in selectedFields
exist in valueProvided
) by creating an object from mapping
the keys in selectedFields
to the key, value pair from valueProvided
:
const selectedFields = ["time", "age", "city"]
const valueProvided = {
"time": "2022-10-01",
"visa": "onArrival",
"age": 30,
"city": "paris",
"hotel": "Holiday"
}
const result = Object.fromEntries(
selectedFields.map(k => [k, valueProvided[k]])
)
console.log(result)
If valueProvided
was an array, you'd need to iterate that using map
:
const selectedFields = ["time", "age", "city"]
const valueProvided = [{
"time": "2022-10-01",
"visa": "onArrival",
"age": 30,
"city": "paris",
"hotel": "Holiday"
},
{
"time": "2022-11-12",
"visa": "preBooked",
"age": 45,
"city": "london",
"hotel": "Business"
}
]
const result = valueProvided.map(v => Object.fromEntries(
Object.entries(v).filter(([k, v]) => selectedFields.includes(k))
// or
// selectedFields.map(k => [k, v[k]])
))
console.log(result)
CodePudding user response:
This is a way to achieve it, I'm not sure whether this qualifies as a shortcut. Let me know:
selectedFields = [ "time", "age", "city" ]
valueProvided = { "time": "2022-10-01", "visa": "onArrival", "age": 30, "city": "paris", "hotel": "Holiday" }
for (let missing of selectedFields.filter(item => (valueProvided[item] !== undefined))) {
delete valueProvided[missing];
}
console.log(valueProvided);
Yes, there is a loop involved in order to remove the elements, but the search for missing elements is being done via calling filter()
.
CodePudding user response:
This should work, although it's defenitely not the shortest answer:
selectedFields = [ "time", "age", "city" ];
valueProvided = { "time": "2022-10-01", "visa": "onArrival", "age": 30, "city": "paris", "hotel": "Holiday" }
console.log(valueProvided)
for (const key of Object.keys(valueProvided)) {
if(! selectedFields.includes(key)){
delete valueProvided[key]
}
}
console.log(valueProvided)
CodePudding user response:
Another "concealed loop" approach using Array.reduce:
valueProvided = {
"time": "2022-10-01",
"visa": "onArrival",
"age": 30,
"city": "paris",
"hotel": "Holiday"
};
selectedFields = ["time", "age", "city"];
function pickProps(fromObject, propNames) {
return propNames.reduce((acc, propName) => {
acc[propName] = fromObject[propName];
return acc
}, {})
}
console.log(pickProps(valueProvided, selectedFields));
This does not mutate the source object. But like others in case property values are not of primitive types, it would reference them.
Direct mutating / re-assigment without helper function would be:
var valueProvided = {
"time": "2022-10-01",
"visa": "onArrival",
"age": 30,
"city": "paris",
"hotel": "Holiday"
};
valueProvided = ["time", "age", "city"].reduce((acc, propName) => {
acc[propName] = valueProvided[propName];
return acc
}, {});
console.log(valueProvided);
"Length golfing" comparison with the fromEntries
approach:
result = selectedFields.reduce((a,k)=>(a[k]=valueProvided[k],a),{})
result = Object.fromEntries(selectedFields.map(k=>[k,valueProvided[k]]))