过滤由 id 键入的 json 并返回一个数组;没有未定义的地图
Posted
技术标签:
【中文标题】过滤由 id 键入的 json 并返回一个数组;没有未定义的地图【英文标题】:filtering in json keyed by id and returning an array; map without undefined 【发布时间】:2017-06-07 06:10:12 【问题描述】:我有
let list =
1: name: "someone1" ,
5: name: "someone5" ,
7: name: "someone7" ,
8: name: "someone8"
;
我想过滤 [1,5,42]
[
name: "someone1" ,
name: "someone5"
]
我试过了
Object.keys(list).map(key=> if([1,5,42].includes(key)) return list[key]);
[
name: "someone1" ,
name: "someone5",
undefined,
undefined
]
PS:当我的列表是一个 json 数组时,我使用了list.filter(person => [1,5].includes(person.id))
。然后我改为通过 id 模型键控,所以我可以使用liat[id]
,这比 list.filter 用于单个元素要快。
【问题讨论】:
【参考方案1】:单线解决方案:
[1,5,42].map(key => list[key]).filter(el => el)
// if(el != null) return true shortened as el => el
Nina Scholz 的简单单行:[1,5,42].reduce((r, k) => r.concat(list[k] || []), []);
的不同之处在于它在将其添加到数组之前进行检查,而上面的行在构建数组后删除了 undefined
s。
另一种可能的单线是:
["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
片段:
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]));
【讨论】:
原始问题中没有出现“单行”的要求。此答案中的javascript
与@NinaScholz 答案中的javascript
有何不同?您是否对每个答案中的javascript
完成流程所花费的时间进行了基准测试?从原始问题中不清楚实际要求是什么?
One liner
不是原来的要求; 你的回答其实就是对我问题的回答,我可以用它;这些只是我想到的其他可能性....【参考方案2】:
您可以直接迭代过滤器数组并获取对象。
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);
如果过滤器包含不是对象键的字符串,则需要一种不同的方法。
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);
一个两步解决方案,其中包含对象的映射值并使用Boolean
过滤真实元素。
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);
【讨论】:
可能是最简单的解决方案 我特别想要 42 部分..!在问题中进行了编辑 所以诀窍是,因为 map 总是返回一些东西,你使用 reduce 并推送到结果数组只有当它不是未定义...? @NinaScholz 现在我们有了答案,效率? :| @ZekeDran,你说的效率是什么意思?哪一个?两者都有 O(n)。【参考方案3】:你可以使用解构赋值
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);
【讨论】:
您能解释一下这是如何工作的吗?(1:res[res.length], 5:res[res.length] = list);
当我有 42 个键(不存在的键)时会发生什么?
@ZekeDran 1:res[res.length]
从对象获取属性"1"
并将值分配给res[res.length]
。在第一个示例中,属性键是显式传递的。在for..of
循环中,当前数组元素是[]
中的计算属性名称。传递42
或"42"
的结果将是结果数组中的undefined
元素。在数组中传递不存在的属性的目的是什么?
列表单独获取,keys数组从服务端单独获取:keys在先!由于我使用的是 redux 存储,因此 list 最初将是 ,这使得键在那时无效,更不用说数组中的几个未定义会折叠整个应用程序
@ZekeDran 您可以在for..of
循环中包含if
语句并使用in
运算符或Object.prototype.hasOwnProperty()
、if (key in list) ([key]:res[res.length] = list)
或if (list.hasOwnProperty(key)) ([key]:res[res.length] = list)
。【参考方案4】:
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);
此解决方案假定您只要求现有密钥。
【讨论】:
谢谢,但我对问题进行了编辑:如果undefined
s 不存在,我特别需要删除它们以上是关于过滤由 id 键入的 json 并返回一个数组;没有未定义的地图的主要内容,如果未能解决你的问题,请参考以下文章
PHP 过滤对象数组并返回新的对象数组,同时基于一个属性删除重复项
Javascript通过包含搜索词的标签子数组过滤或减少每个JSON对象