用例是将对象数组转换为哈希映射,其中一个属性是键,另一个属性是值。使用此功能的常见情况是将超媒体响应中的“链接”对象转换为链接的哈希图。

jsfiddle

看起来更具可读性,但效率较低。 toHashMap似乎在以牺牲可读性为代价的情况下具有最佳效率。我怀疑Lodash可能已经具有执行此操作的功能,但是在查看API文档后我没有找到类似的信息。

评论

我已经编译了在此lodash功能请求(目前需要upvotes!)中将对象转换为数组的最常用方法。

#1 楼

我认为您正在寻找_.keyBy(或旧版本中的_.indexBy

_.keyBy(data, 'rel');


评论


\ $ \ begingroup \ $
我不明白为什么这是可接受的答案,因为它给出的结果与公开的函数不一样
\ $ \ endgroup \ $
–保罗·弗拉克(PauFracés)
15年2月17日在15:53

\ $ \ begingroup \ $
@PauFracés修改后的解决方案请参见下文。
\ $ \ endgroup \ $
– Pete
15年3月13日在21:14

\ $ \ begingroup \ $
注意:现在称为_.keyBy(lodash.com/docs#keyBy)。
\ $ \ endgroup \ $
– 2540625
16-2-18的2:07

#2 楼

经修订的解决方案

根据上面的PauFracés评论,这是完整的解决方案。约翰·安德森(John Anderson)给出的解决方案将通过键索引所有对象。但是,这不会创建键-值对映射。

要完成生成完整哈希图​​的解决方案,必须将值映射到键。使用mapValues函数,可以从对象中提取值,然后将其映射回键,或者在这种情况下,将其映射回键。
将所有值映射到该键。

代码

下面是启用了日志记录的完整代码。对于非日志记录版本,请使用rel函数删除所有行。




 tap 

 var data = [{ rel: 'link1', href: 'url1' }, 
            { rel: 'link2', href: 'url2' }, 
            { rel: 'link3', href: 'url3' },
            { rel: 'link4', href: 'url4' }];

function log(value) {
  document.getElementById("output").innerHTML += JSON.stringify(value, null, 2) + "\n"
}

var hashmap = _.chain(data)
  .keyBy('rel')

  .tap(log) // Line used just for logging

  .mapValues('href')

  .tap(log)
  
  .value(); 




评论


\ $ \ begingroup \ $
好的解决方案!我个人会选择mapValues而不是transform。使用transform,您可以在闭包外部更新状态(这是一个副作用函数),而使用mapValues则不是。
\ $ \ endgroup \ $
–马丁(Martijn)
15年7月7日在9:14

\ $ \ begingroup \ $
@Martijn很好的建议!使一个更清洁的解决方案恕我直言。我已根据您的建议更新了解决方案。谢谢!
\ $ \ endgroup \ $
– Pete
15年7月10日在20:21

\ $ \ begingroup \ $
@Pete太棒了!刚意识到lodash v4将indexBy重命名为keyBy
\ $ \ endgroup \ $
–保罗·弗拉克(PauFracés)
16-2-11在20:22



\ $ \ begingroup \ $
更新为使用keyBy
\ $ \ endgroup \ $
– Pete
16 Mar 8 '16 at 13:18

\ $ \ begingroup \ $
使用lodash-fp,这也可以作为单线流程完成(fpKeyBy('rel'),fpMapValues('href'))(data)(fp前缀函数是fp-lodash版本)
\ $ \ endgroup \ $
–西班牙火车
16年5月7日,0:05

#3 楼

在ES7中,它现在变得很简单: br />

评论


\ $ \ begingroup \ $
如果有效的话会很棒。但它似乎不起作用! (节点5.0.0)
\ $ \ endgroup \ $
–雷恩·伍勒(Rene Wooller)
16 Sep 8'在0:55



\ $ \ begingroup \ $
这是ES7,而不是ES2015
\ $ \ endgroup \ $
–雷恩·伍勒(Rene Wooller)
2016年9月8日,下午1:01

\ $ \ begingroup \ $
@ReneWooller对,对不起。使用Babel时很难追踪什么
\ $ \ endgroup \ $
–hon2a
16 Sep 8'9:15



\ $ \ begingroup \ $
可行,不必具有lodash依赖关系很好,但是如果lodash方法的可读性不超过一百万倍,那就该死了。
\ $ \ endgroup \ $
– Thor84no
18年1月29日在10:31

\ $ \ begingroup \ $
@digitai我的意思主要是,您现在可以轻松地用纯JS内联它。显然,您可以为其创建一个抽象,但是您可能还希望使其更高效(例如,避免在每次通过时都创建一个新对象)。如果键和值属性名称将是外部变量,则将您解构为{[keyProp]:键,[valueProp]:值}。
\ $ \ endgroup \ $
–hon2a
4月1日8:36



#4 楼

一种更简单的方法是使用“减少”。

您可以使用“累加器”(在本例中为新对象)遍历源数组。在上方,我们使用rel属性(以href为值)来键入哈希值。

评论


\ $ \ begingroup \ $
您还可以使用.transform减少代码量...但这是个人喜好问题。
\ $ \ endgroup \ $
– Pete
16-3-14在15:22

\ $ \ begingroup \ $
如Martijn在先前的评论中所述,.reduce和.transform都在闭包外部更新状态,而mapValues没有。因此,在使用.reduce时请记住这一点。
\ $ \ endgroup \ $
– Pete
16 Mar 16 '16 at 21:37

\ $ \ begingroup \ $
@Pete更新外部状态不是.reduce的固有属性,而是reducer本身的固有属性。您也可以使用.reduce而没有副作用(请参阅我的简短回答)。
\ $ \ endgroup \ $
–hon2a
16-3-24在10:42



\ $ \ begingroup \ $
@ hon2a是的...我有一个让我感到困惑的特别的减少方法的事情是,“ rel”和“ href”被硬编码到回调中。它使可重用性降低。我尝试在原始解决方案中避免这种情况。一线到五线的维护成本对我来说更具吸引力。至于可读性,与非程序员相比,与keyBy和mapValues相比,reduce的流畅性较低。当然,所有这些都是以性能为代价的,因此这并不是所有解决方案的终点。感谢您更新到ES2015。
\ $ \ endgroup \ $
– Pete
16-3-24在13:40



\ $ \ begingroup \ $
@Pete我认为,简单地使用reduce实际上比keyBy + mapValues(propNameShortcut)更具可读性,因为reduce是一种本机(因此无处不在)方法,不需要您知道a特定的(Lodash)API。
\ $ \ endgroup \ $
–hon2a
16年4月11日在10:39

#5 楼

从lodash 4开始,您可以使用_.fromPairs:

var data = [
    { rel: 'link1', href: 'url1'},
    { rel: 'link2', href: 'url2'},
    { rel: 'link3', href: 'url3'},
    { rel: 'link4', href: 'url4'},
];

var hashmap = _.fromPairs(data.map(function(item) {
   return [item.rel, item.href];
}));


评论


\ $ \ begingroup \ $
是否有一种方法可以在map方法之外对'rel'和'href'进行参数化,以使解决方案更通用?
\ $ \ endgroup \ $
– Pete
16年5月25日在14:21

\ $ \ begingroup \ $
函数makePair(keyProperty,valueProperty){返回函数(item){返回[item [keyProperty],item [valueProperty]]; }; } var hashmap = _.fromPairs(data.map(makePair('rel','href'))));
\ $ \ endgroup \ $
–里卡多·斯图文(Ricardo Stuven)
17年8月28日在13:20



#6 楼

使用Lodash 4:

使用keyBymapValues

_.mapValues(_.keyBy(data, 'rel'), v => v.href);


或:

_.chain(data).keyBy('rel').mapValues(v => v.href).value();


#7 楼

我已经看到很多很好的答案。我想使用Ramda的indexBy向列表添加一个答案。




 const data = [{
    id: 1,
    foo: 'bar'
  },
  {
    id: 2,
    baz: 'lorem'
  }
];

const dataById = R.indexBy(R.prop('id'), data);
console.log(dataById) 

 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script> 





我希望它对其他人有帮助:)

评论


\ $ \ begingroup \ $
这不是对所提供代码的真正审查,对吗?
\ $ \ endgroup \ $
–桅杆
18年1月15日在20:20

\ $ \ begingroup \ $
对不起,误解了本网站的使用。更熟悉StackOverflow :)
\ $ \ endgroup \ $
– Abhishek Ghosh
18年1月16日,0:33