【问题标题】:Mapping an array of objects to key/value pairs in CoffeeScript将对象数组映射到 CoffeeScript 中的键/值对
【发布时间】:2012-01-11 00:36:26
【问题描述】:

我有一个元素数组,我想应用映射将其转换为单个对象上的键值对(以模拟关联数组)。

Can destructuring assignment be used to effect a projection in CoffeeScript? 中的方法似乎对我不起作用,因为它会生成一个简单的数组而不是键/值对。

我选择的语言是 CoffeeScript 或 JavaScript。

一个例子:

[{name: 'a', value: 'b', other: 'c'}, {name: 'd', value: 'e', other: 'f'}]

应该转化为:

{
  a: 'b',
  d: 'e'
}

单行是首选。 ;-)

【问题讨论】:

  • 建议你在没有jquery依赖的纯coffeescript中做一个例子;可以自己测试的东西。如果你不明白,也许我们其他人可以。
  • Marius Kjeldahl:完成。希望这更清楚一点。
  • “首选单行”?真的吗? # 行数!== 质量。
  • 马特麦克唐纳:同意。尽管如此,如果有一个明确的单行,我倾向于使用那个而不是多语句解决方案。恕我直言,reduce 方法是合格的(即使它需要一个实用方法)。
  • tokland:还没有,但我不排除。

标签: javascript jquery coffeescript


【解决方案1】:

ES6 单行:

const data = [{name: 'a', value: 97}, {name: 'b', value: 98}]

data.reduce((obj, e) => ({...obj, [e.name]: e.value}), {})

【讨论】:

    【解决方案2】:

    或者使用普通的 ES6:

    const old = [
      {name: 'a', value: 'b', other: 'c'}, 
      {name: 'd', value: 'e', other: 'f'}
    ]
    
    const transformed = Object.assign(
      {}, 
      ...old.map(({name, value}) => ({ [name]: value }))
    );
    
    console.log(transformed);

    【讨论】:

    • 这是一个热门的单线 - 但你能解释一下这部分吗? old.map(({name, value}) => ({ [name]: value })) => ( ) 在做什么?它返回一个带有变量名的键值对,但我没有得到 () 或 [] 部分。
    • 它返回一个键值对,实际上是一个变量键,始终是 name 值,而值是旧对象的 value 值。所以它返回{a: 'b'},它将被分配给空对象。清除吗?
    • 我花了很多时间寻找我现在理解的称为计算属性名称 ({[key]: value}),这个答案是我最终知道要搜索什么所需的线索。谢谢!
    【解决方案3】:

    使用Array.prototype.reduce()

    var arrayOfObjects = [
                  {name: 'a', value: 'b', other: 'c'}, 
                  {name: 'd', value: 'e', other: 'f'}
                ];
    
    arrayOfObjects.reduce(function(previousValue, currentValue, currentIndex) {
      previousValue[currentValue.name] = currentValue.value;
      return previousValue;
    }, {})
    

    【讨论】:

      【解决方案4】:

      看看http://coffeescriptcookbook.com/chapters/arrays/creating-a-dictionary-object-from-an-array

        myArray = [{name: 'a', value: 'b', other: 'c'}, {name: 'd', value: 'e', other: 'f'}]
        dict = {}
        dict[obj['name']] = obj['value'] for obj in myArray when obj['name']?
        console.log(JSON.stringify(dict, 0, 2));
      

      这正是你想要的。

      【讨论】:

        【解决方案5】:
        var arr = [{name: 'a', value: 'b', other: 'c'}, {name: 'd', value: 'e', other: 'f'}];
        
        var obj = arr.reduce(function ( total, current ) {
            total[ current.name ] = current.value;
            return total;
        }, {});
        

        纯 JavaScript。它实际上是一个班轮,看起来很轴。

        Array.prototype.reduce 是 ES5,但不难填充。这是一个示例 shim:

        Array.prototype.reduce = function ( fun, initVal ) {
            var sum = initVal || this[ 0 ],
                i = 1, len = this.length;
        
            do {
                sum = fun.call( undefined, sum, this[i], i, this );
            } while ( ++i < len );
        
            return sum;
        };
        

        arr.reducearr.map 的高级版本,arr.forEach 是高级版本。您可以这样做以获得相同的效果:

        var obj = {};
        arr.forEach(function ( val ) {
            obj[ val.name ] = val.value;
        });
        
        //and using jQuery.each
        var obj = {};
        $.each( arr, function ( index, val ) {
            obj[ val.name ] = val.value;
        });
        
        //latter version in coffeescript:
        obj = {}
        $.each( arr, (index, val) ->
            obj[ val.name ] = val.value
        )
        

        【讨论】:

        • 你确定i的初始化是正确的吗?如果有一个 initVal 并且只有一个数组元素,则永远不会调用 fun。
        • @Zirak 很好。 obj = arr.reduce ((o, item) -&gt; o[item.name] = item.value; o), {} 在咖啡脚本中。
        • @Thilo-AlexanderGinkel 这是一个不错的可靠垫片集合:github.com/kriskowal/es5-shim
        • @Thilo-AlexanderGinkel 不错的收获。修复并添加了替代方案。
        • 有点老了,不过可以把js版本简化成arr.reduce(function ( total, current ) { return total[ current.name ] = current.value, total }, {})
        【解决方案6】:
        values = {}
        values[name] = value for {name, value} in arr
        

        或在 javascript 中:

        var values = {}
        arr.forEach(function(o){
            values[o.name] = o.value
        })
        

        这几乎正是 CoffeeScript 编译成的内容。

        【讨论】:

          【解决方案7】:

          要修复语法错误,您必须将{ @name: @value } 扩展为:

          o = {}; o[@name] = @value; o
          

          然后您可以将对象与$.extend() 和一个 splat 合并(使用空对象以避免意外扩展 jQuery):

          $.extend {}, $(row).children('input').map(() -> o = {}; o[@name] = @value; o)...
          

          不过,更简单的选择就是使用 2-liner:

          result = {}
          $(row).children('input').each(() -> result[@name] = @value)
          

          【讨论】:

          • 如果你真的需要,你可以把初始化扔到回调中 (result?={})[@name]...
          猜你喜欢
          • 2019-04-28
          • 1970-01-01
          • 2018-03-10
          • 2019-09-25
          • 2020-07-22
          • 1970-01-01
          • 1970-01-01
          • 2020-10-02
          • 2017-08-25
          相关资源
          最近更新 更多