在Coffeescript中,如何通过一个属性对一组对象进行分组?

时间:2015-11-10 20:49:38

标签: javascript arrays coffeescript

让我们说我有一系列像这样的对象:

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。

3 个答案:

答案 0 :(得分:1)

我认为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]可以查看第一个元素。一元+运算符可以将您的字符串高度转换为数字高度,以便它们比较您可能期望的方式。

答案 1 :(得分:1)

这是我能想到的。因为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' 
    }
  ]
]

答案 2 :(得分: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]