按 id 规范化对象数组和键

Posted

技术标签:

【中文标题】按 id 规范化对象数组和键【英文标题】:Normalise array of objects & key by id 【发布时间】:2017-06-15 21:32:00 【问题描述】:

我希望规范化从 API 返回的一些数据。已经在项目中使用下划线。

var res = [
    badge_no: 123,
    id: 1,
    name: 'bob'
  , 
    badge_no: 456,
    id: 2,
    name: 'bill'
  , 
    badge_no: 789,
    id: 3,
    name: 'ben'
  ,
  // etc
];

我希望创建一个如下所示的数据结构:

var normalisedRes = [
  1: 
    badge_no: 123,
    id: 1,
    name: 'bob'
  
, 
  2: 
    badge_no: 456,
    id: 2,
    name: 'bill'
  
, 
  3: 
    badge_no: 789,
    id: 3,
    name: 'ben'
  
];

将 id 保存在 obj 中很重要。我相信我可以通过 reduce 完成此任务,但我正在苦苦挣扎。

感谢您的帮助!

编辑:这个问题现在已经得到解答。

根据这里的一些建议,我决定对数据进行规范化以返回一个 obj,如下所示:

 '1': data, '2':data, '3':data 

为此,我使用了 reduce,正如我最初认为的那样:

var normalised = res.reduce((acc, person) => acc[person.id] = person; return acc; , );

再次感谢大家的回答!

【问题讨论】:

你能分享你到目前为止尝试过的代码吗? 所以你想要一个对象数组,每个对象都包含一个键(它的id)?那是您开始时的“更好”或标准化版本吗?你为什么想要那个结构? 最终结构没有意义。为什么需要一个数组来包装一个对象? 您希望密钥是IDs 还是indexes (+1) 请在您的问题中编辑您关于键是 ID 的最后评论。此外,避免在您的问题中编辑答案,而是接受其中一个答案,如有必要,请在最终决定中对其进行评论。如果没有一个答案符合您的需要,我们鼓励您提供自己的答案并接受它。 【参考方案1】:

_.indexBy 完全符合要求。

【讨论】:

【参考方案2】:

这些解决方案不是与直觉相反吗,在数组上使用 HashTable 的重点是,如果必须使用 Array.find((item)=>...) 它必须遍历每条记录为了找到你想要的,reduce 会遍历数组中的每一项,map 会返回一个新数组,即:你会得到一个带有 objectKey:...object 的数组,最好的办法是是从您的后端返回一个哈希,这实际上是 firebase 所做的,例如

【讨论】:

【参考方案3】:

您可以将Array#map 与对象一起使用,并使用id 设置键并返回该对象。

var array = [ badge_no: 123, id: 1, name: 'bob' ,  badge_no: 456, id: 2, name: 'bill' ,  badge_no: 789, id: 3, name: 'ben' ],
    result = array.map(function (a) 
        var o = ;
        o[a.id] = a;
        return o;
   );

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

使用 ES6,您可以使用计算属性。

var array = [ badge_no: 123, id: 1, name: 'bob' ,  badge_no: 456, id: 2, name: 'bill' ,  badge_no: 789, id: 3, name: 'ben' ],
    result = array.map(a => ( [a.id]: a ));

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

虽然是正确的答案,难道不应该等待OP分享努力吗? 我觉得链接不对……不是Map,是Array.prototype.map【参考方案4】:

您可以通过Array#map() 做到这一点

var res = [badge_no:123, id:1, name:'bob',badge_no:456, id:2, name:'bill',badge_no:789, id:3, name:'ben'];

var result = res.map(e => ([e.id]: e))
console.log(result)

如果您愿意,也可以使用reduce(),但map() 应该可以完成工作。

var res = [badge_no:123, id:1, name:'bob',badge_no:456, id:2, name:'bill',badge_no:789, id:3, name:'ben'];

var result = res.reduce((r, e) => (r.push([e.id]: e), r), [])
console.log(result)

【讨论】:

虽然是正确的答案,难道不应该等待OP分享努力吗?【参考方案5】:

您不能使用整数作为对象的键。所以你的例子是不可能的。 请参阅此相关问题:javascript: Using integer as key in associative array?

【讨论】:

你可以使用任何类型的键,它会自动装箱成一个字符串 这通常是不好的做法,因为它会强制您访问对象内部的属性,例如console.log(normalisedRes["3"]) 而不是像 console.log(normalisedRes.3) 这样会产生错误。 normalisedRes[3] 也可以工作,并且在将计算键的自动化过程中,您必须使用括号语法访问值 虽然这是不好的做法,但这正是 OP 想要的。这个答案对了一半。这个例子可能的。

以上是关于按 id 规范化对象数组和键的主要内容,如果未能解决你的问题,请参考以下文章

数组里面获取键名和键值

使用嵌套对象和键对数组建模

使用对象和键迭代 NSArray 的最快方法

按id typescript对对象数组进行分组[重复]

按数组过滤对象数组

MongoDB中的规范化对象和数组