Underscore.js - 将键/值对数组映射为对象 - 一行代码

46

我一直在查看underscore文档,但似乎找不到一个方法(或嵌套的方法调用)来完成以下转换:

假设我有以下Javascript数组:

 [{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12}, ... ]

我需要将它转换为以下对象:

 {
      sEcho: 1,
      iColumns: 12,
      ...
 }

我使用underscore.js是有原因的,所以它必须是一行代码。


1
一行代码?_.map(arr,function(v,o){o={};return o[v.name]=v.value,o }); 不确定是否有更短的方法... - elclanrs
@elclanrs 这将创建一个对象数组。你只需要一个对象。 - Aadit M Shah
@AaditMShah:好的,我误解了... - elclanrs
9个回答

60

使用_.object的“数组对”签名对Sza的答案进行变化:

_.object(_.map(data, function(x){return [x.name, x.value]}))

2
不错!如果你使用TypeScript,甚至可以节省几次按键的操作 😉_.object(_.map(data, (x) => {return [x.name, x.value]})) - parliament
1
@parliament 或 coffeescript :-) - John Dvorak
3
另外,Sza的示例可以在没有zip的情况下运行(因为object接受单个名/值对数组或两个不同的数组)。因此,你可以这样做_.object(_pluck(data,'name'), _.pluck(data,'value')) - ShawnFumo
2
说到其他编程语言,最清晰的可能是在计算机科学中使用理解:_.object([o.name, o.value] for o in data) - ShawnFumo
使用_.chain函数可能会更清晰:https://gist.github.com/ablanchet/f8b9c3ece0812ebf3f3c - Antoine Blanchet
pluck版本的缺点是它需要两次遍历数据(pluck / pluck),然后再次生成结果(object):map解决方案只需要一次遍历数据(map),然后再次遍历结果(object)。 - Dtipson

53

因为没有人把这个作为答案发布,所以我发布了它,因为我认为它比 Jan的答案 更好。它更短,没有内联函数,更加简洁。

_.object(_.pluck(data, 'name'), _.pluck(data, 'value'));

2
据我所知,下划线不会明确保证pluckmap的结果顺序,因此即使这在当前浏览器中可行,我也不会依赖它。试想一下跟踪错误并找到值分配给错误键的bug将是多么困难。 - peterp
你说的没错,不过我想指出的是,楼主并没有明确要求相同的顺序。 - Brad Pitcher
我并不担心映射中键值对的顺序(据我所知,在JS中没有关于此的保证),而是担心将值分配给错误的键。有时,在某些浏览器中,提取名称可能会返回与提取值不同的顺序,这将完全破坏您的数据并返回例如{sEcho:12,iColumns:1}而不是预期结果。这就是为什么我更喜欢在单个操作中执行键值映射,例如reducemap - peterp
@peterp 我明白了。但是在这种情况下,pluckmapobject函数都是在数组上操作的,其中顺序是有保证的,所以没有问题。 - Brad Pitcher
同意,目前的underscore.js实现在这方面是安全的;但是没有明确的保证,实现可能在未来版本中有所不同。我关于“某些浏览器”的想法肯定是错误的,需要“其他版本的underscore.js”才能破坏代码,感谢您的提醒。请随意称呼我为多疑,但我仍然不愿意依赖顺序。 :) - peterp
一种健康的多虑总是一件好事。:-) 我认为 Underscore 得非常努力才能搞砸它,因为我们从未将任何对象传递给它来处理。 - Brad Pitcher

27
这应该就可以了:
_.reduce(array, function(o, v){
    o[v.name] = v.value;
    return o;
}, {});
作为一行代码(你在开玩笑吧,对吧?):
_.reduce(array,function(a,b){a[b.name]=b.value;return a},{});

你为什么要对 b.value 的值求和?为什么不直接使用 a[b.name] = b.value 呢? - mu is too short
@muistooshort 我以为它应该对它们求和,不太清楚为什么 xD - Esailija
5
我没有看到任何求和的要求。如果他们试图用一行代码来显示聪明(还会有其他原因吗?),那么你可以毫不掩饰地表达对维护者的仇恨,并加上逗号运算符: _(a).reduce(function(m, h) { return m[h.name] = h.value, m }, { })。嘿。 - mu is too short
@muistooshort 嗯,我猜那只是个脑抽,我现在已经删除了求和。顺便说一下,我使用闭包编译器生成了这个偏爱分号的单行代码:P - Esailija
1
@muistooshort:我一定会留下评论的 8-) - parliament
1
这个答案是最高效的,因为它只需要遍历一次原始数组。 - artur grzesiak

7
var names = _.pluck(data, 'name');
var values = _.pluck(data, 'value');
var result = _.object(_.zip(names, values));
console.log(result);

2
虽然有趣的是,我们需要使用三种不太常见、有点专业的方法才能做到与一个相对较为常见的方法(reduce)同样数量的代码。+1 - Esailija

6
假设您有以下JavaScript数组:
var list = [
    {
         name: "sEcho",
         value: 1
    },
    {
         name: "iColumns",
         value: 12
    },
    ...
];

您可以按照以下方式将其转换为所需格式:
var table = _.reduce(list, function (table, item) {
    table[item.name] = item.value;
    return table;
}, {});

这并不是一个一行命令,但我认为你并不是真的想要一个一行命令。是吗?

如果你真的需要一个一行命令,这里有一个:

var t = _.reduce(list, function (t, i) { return t[i.name] = i.value, t; }, {});

是的,其他人已经提供了相同的答案。但这只是因为你的问题的答案非常简单。


3
var a =  [{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12} ];

var o = {}; _.each(a, function(e) { o[e.name] = e.value; });

console.log(o);
// Object {sEcho: 1, iColumns: 12} 

2

我认为使用reduce是非常完美的选择:

_.reduce(ary, function(memo, obj){ memo[obj["name"]] = obj["value"]; return memo }, {});


0
var arr = [{ "name" : "sEcho", "value" : 1},{ "name" : "iColumns", "value" : 12}]

ES6

_.mapObject( _.indexBy(arr, 'name'), (v) => v.value )

ES5

_.mapObject( _.indexBy(arr, 'name'), function (v) { return v.value; } )

这个会迭代两次


-1
一个更好、更简单的方法,是我偶然发现的。

<script type="text/javascript">
  
        var obj = {
            Company: "GeeksforGeeks",
            Address: "Noida",
            Contact: "+91 9876543210",
            Email: "abc@gfg.com"
        }
        console.log(_.keys(obj));
    </script>

来源:https://www.geeksforgeeks.org/underscore-js-_-keys-function/


这只做了相反的一半。 - Julian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接