Home > Software design >  Is there a ES6 shortcut way to compare array of elements and object key and remove the non-matching
Is there a ES6 shortcut way to compare array of elements and object key and remove the non-matching

Time:10-14

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]]))
  • Related