【问题标题】:In Coffeescript, how would I group an array of objects by one property?在 Coffeescript 中,如何按一个属性对一组对象进行分组?
【发布时间】:2016-02-11 21:11:12
【问题描述】:

假设我有一个这样的对象数组:

var array = [
    {name:"aaa", height:"20"},
    {name:"bbb", height:"100"},
    {name:"ccc", height:"20"},
    {name:"ddd", height:"20"},
    {name:"eee", height:"100"},
]

在这种情况下,我想按高度对其进行分组,所以我最终得到一个不同的数组,该数组具有组名,然后是该组中的每个项目,如下所示:

var grouped_by_height = [
    [{name:"aaa", height:"20"}, {name:"ccc", height:"20"}, {name:"ddd", height:"20"}],
    [{name:"bbb", height:"100"}, {name:"eee", height:"100"}]
]

我在 JS/jQuery 中编写了一个很长的解决方案,但我想知道是否有一种快速简便的方法来做到这一点是 Coffeescript。

【问题讨论】:

  • CoffeeScript 只是 JavaScript 的一种不同语法。除了列表推导的简写外,它不提供任何数据操作机制。

标签: javascript arrays coffeescript


【解决方案1】:
array = [
    {name:"aaa", height:"20"},
    {name:"bbb", height:"100"},
    {name:"ccc", height:"20"},
    {name:"ddd", height:"20"},
    {name:"eee", height:"100"},
]

# unique heights
uniq = array.reduce (memo, el) ->
  memo.push(el.height) if memo.indexOf(el.height) is -1
  memo
, []

# output grouped by height
out = [[obj for obj in array when obj.height is height][0] for height in uniq][0]

【讨论】:

    【解决方案2】:

    我认为 CoffeeScript 中没有什么特别之处可以帮助您(或者至少没有什么可以解决困难的部分)。我可能会使用Array.prototype.reduce 来完成类似这样的繁重工作:

    group_by_height = (groups, obj) ->
        groups[obj.height] ?= [ ]
        groups[obj.height].push(obj)
        groups
    grouped_obj = array.reduce(group_by_height, { })
    grouped_by_height = (v for k, v of grouped_obj)
    

    虽然这不能保证 grouped_by_height 中的任何特定顺序,但可以通过添加排序步骤轻松解决:

    by_height = (a, b) -> +a[0].height - +b[0].height
    group_by_height = (v for k, v of grouped_obj).sort(by_height)
    

    您将对数组进行排序,因此 ab 将是数组,因此 [0] 将查看第一个元素。一元 + 运算符用于将您的字符串高度转换为数字高度,以便它们按照您可能期望的方式进行比较。

    【讨论】:

      【解决方案3】:

      这是我能想到的。由于 mu 太短了,coffeescript 没有什么魔力,但有一些内置的东西可以帮助它。唯一的问题是编译后的 js 版本最终会比你用纯 js 编写的要长。

      groupByKey = (array, key) ->
        grouped = {}
        for obj in array
          grouped[obj[key]] ?= []
          grouped[obj[key]].push obj
        Object.keys(grouped).map (group) ->
          grouped[group]
      

      自己试试吧:

      array = [
        {
          name: 'aaa'
          height: '20'
        }
        {
          name: 'bbb'
          height: '100'
        }
        {
          name: 'ccc'
          height: '20'
        }
        {
          name: 'ddd'
          height: '20'
        }
        {
          name: 'eee'
          height: '100'
        }
      ]
      
      groupByKey = (array, key) ->
        grouped = {}
        for obj in array
          grouped[obj[key]] ?= []
          grouped[obj[key]].push obj
        Object.keys(grouped).map (group) ->
          grouped[group]
      
      console.log groupByKey(array, 'height')
      

      输出是:

      [
        [
          { 
            name: 'aaa',
            height: '20' 
          },
          { 
            name: 'ccc',
            height: '20' 
          },
          { 
            name: 'ddd',
            height: '20' 
          } 
        ],
        [ 
          { 
            name: 'bbb',
            height: '100'
          },
          { 
            name: 'eee',
            height: '100' 
          }
        ]
      ]
      

      【讨论】:

        猜你喜欢
        • 2021-11-25
        • 2022-01-08
        • 1970-01-01
        相关资源
        最近更新 更多