filtering in json keyed by id and returning an arr

2020-04-23 06:22发布

问题:

I have

let list = { 
  1: { name: "someone1" },
  5: { name: "someone5" },
  7: { name: "someone7" },
  8: { name: "someone8" }
};

and I want to filter [1,5,42]

[
 { name: "someone1" },
 { name: "someone5" }
]

I tried

Object.keys(list).map(key=> {if([1,5,42].includes(key)) return list[key]});

[
 { name: "someone1" },
 { name: "someone5"},
 undefined, 
 undefined
]

PS: When my list was a json array, I used list.filter(person => [1,5].includes(person.id)). I then changed to keyed by id model, so I can use liat[id] which is way faster than list.filter for single element.

回答1:

You could directly iterate the filter array and take the object.

let list = { 1: { name: "someone1" }, 5: { name: "someone5" }, 7: { name: "someone7" }, 8: { name: "someone8" } },
    filter = [1, 5],
    result = filter.map(k => list[k]);

console.log(result);

You need a different approach, if the filter contains strings, which are not keys of the object.

let list = { 1: { name: "someone1" }, 5: { name: "someone5" }, 7: { name: "someone7" }, 8: { name: "someone8" } },
    filter = [1, 5, 42],
    result = filter.reduce((r, k) => r.concat(list[k] || []), []);

console.log(result);

A two step solution with mapping values of the object and filtering with Boolean for truthy elements.

let list = { 1: { name: "someone1" }, 5: { name: "someone5" }, 7: { name: "someone7" }, 8: { name: "someone8" } },
    filter = [1, 5, 42],
    result = filter.map(key => list[key]).filter(Boolean);

console.log(result);



回答2:

You can use destructuring assignment

let res = [];
({1:res[res.length], 5:res[res.length]} = list);

let list = { 
  1: { name: "someone1" },
  5: { name: "someone5" },
  7: { name: "someone7" },
  8: { name: "someone8" }
};

let [keys, res] = [["1", "5"], []];

for (let key of keys) {({[key]:res[res.length]} = list)}

console.log(res);



回答3:

let list = { 
  1: { name: "someone1" },
  5: { name: "someone5" },
  7: { name: "someone7" },
  8: { name: "someone8" }
};
function filter(ids, list){
  var ret = [];
  for(var i in ids){
    var id = ids[i];
    ret.push(list[id]);
  }
  return ret;
}
var filtered = filter([1,5], list);
console.log(filtered);

this solution assumes you only ask for existing keys.



回答4:

A one-liner solution:

[1,5,42].map(key => list[key]).filter(el => el)
// if(el != null) return true shortened as el => el

Nina Scholz's simple one liner: [1,5,42].reduce((r, k) => r.concat(list[k] || []), []); is different in that it checks before adding it to the array while the above one removes undefineds after building the array.

One more possible one-liner would be:

["1","5","42"].filter(key => Object.keys(list).includes(key)).map(key => list[key])
//This one removes the invalid keys and then build an array without `undefined`s

Snippet:

let list = { 
  1: { name: "someone1" },
  5: { name: "someone5" },
  7: { name: "someone7" },
  8: { name: "someone8" }
};

console.log([1,5,42].map(key => list[key]).filter(el => el));

console.log(["1","5","42"].filter(key => Object.keys(list).includes(key)).map(key => list[key]));