1

我怎样才能打开这个对象数组(其中有一些重复的对象):

items =
  [
    { TYPEID: 150927,  NAME: 'Staples',    COLOR: 'Silver' },
    { TYPEID: 1246007, NAME: 'Pencils',    COLOR: 'Yellow' },
    { TYPEID: 1246007, NAME: 'Pencils',    COLOR: 'Blue'   },
    { TYPEID: 150927,  NAME: 'Staples',    COLOR: 'Black'  },
    { TYPEID: 1248350, NAME: 'Staples',    COLOR: 'Black'  },
    { TYPEID: 1246007, NAME: 'Pencils',    COLOR: 'Blue'   },
    { TYPEID: 150927,  NAME: 'Staples',    COLOR: 'Silver' },
    { TYPEID: 150927,  NAME: 'Fasteners',  COLOR: 'Silver' }
  ]

进入这个:

items =
  [
    { TYPEID: 150927,  NAME: 'Staples',    COLOR: 'Silver' },
    { TYPEID: 1246007, NAME: 'Pencils',    COLOR: 'Yellow' },
    { TYPEID: 1246007, NAME: 'Pencils',    COLOR: 'Blue'   },
    { TYPEID: 150927,  NAME: 'Staples',    COLOR: 'Black'  },
    { TYPEID: 1248350, NAME: 'Staples',    COLOR: 'Black'  },
    { TYPEID: 150927,  NAME: 'Fasteners',  COLOR: 'Silver' }
  ]

...通过过滤掉两个重复的对象(银色订书钉和蓝色铅笔)?

似乎应该有一个简单的方法来做到这一点,但我还没有找到一个简单的解决方案。

我见过一些 javascript / jquery 代码可以做到这一点,但我不是最擅长将它们转换成咖啡脚本。

更新:

通常会有不同的对象具有非常相似的属性。

在实际应用中,每个对象都有 25 个属性的潜力。

如果每个属性都相等,我只想删除对象。

更新 2

这是最终为我工作的代码 - (感谢rjz

unique = (objAry, callback) ->
  results = []

  valMatch = (seen, obj) ->
    for other in seen
      match = true
      for key, val of obj
        match = false unless other[key] == val
      return true if match
    false

  objAry.forEach (item) ->
    unless valMatch(results, item)
      results.push(item)
  callback null, results

这就是我所说的:

unique items, (err, items) ->
  console.log items
4

4 回答 4

2

根据您想要检查相等性的深度,您可能只是假设该USERID字段的唯一性并执行以下操作:

ids = []    # Contains list of "seen" IDs
result = [] # Contains list of unique users

users.forEach (u) -> 
  if result.indexOf(u.USERID) == -1
    result.push(u)
    ids.push(u.USERID)

如果您需要进行更深入的匹配并且没有可用的主键(可能是更大问题的标志),您可以创建一个更复杂的相等测试:

valMatch = (seen, obj) ->
  for other in seen
    match = true
    for key, val of obj
      match = false unless other[key] == val
    return true if match
  false

result = []
seen = []

data.forEach (datum) -> 
  unless valMatch(result, datum)
    result.push(datum)
    seen.push(datum)
于 2012-12-07T17:53:42.843 回答
0

我会使用 underscore.js 并尝试这样的事情

result = item[0] for item in _.groupBy(users, (user) => user.USERID)

它没有经过测试;-) 显然这假设我们只检查 USERID

如果您不能只检查 USERID,您当然可以将所有对象转换为 json 字符串,然后比较 json 字符串

result = item[0] for item in _.groupBy(users, (user) => user.toJSON())

显然,这是一个肮脏的 hack,它依赖于所有浏览器和引擎按创建/分配顺序序列化对象及其插槽的事实。

因此,无论如何,rjz 的解决方案肯定是更好的解决方案,但这很可能也有效。

于 2012-12-07T19:50:18.293 回答
0

这是一个老问题 - 但老歌是......

让我们加入数组中的对象:(将所有值放入一个数组并将其加入一个字符串)

join_object=(o)->
    ["#{attr}:#{value}" for attr, value of o].join() 

这会为每个 obj 生成类似的输出。

    TYPEID:150927,NAME:Staples,COLOR:Silver     

并让我们对“独特”数组的咖啡方式进行深度独特的修改:

Array::unique_deep = ->
    output = {}
    output[join_object(@[key])] = @[key] for key in [0...@length]
    value for key, value of output      

短而节省。

结果:

Array::unique_deep = ->
    join_object=(o)->
        ["#{attr}:#{value}" for attr, value of o].join()
    output = {}
    output[join_object @[key]] = @[key] for key in [0...@length]
    value for foo_key, value of output                          
于 2019-07-27T03:31:25.103 回答
-2
Array::uniq = ->
    unique=(v, k, self) ->
        self.indexOf(v)==k
    @.filter(unique)

# console.log([1,2,3,3,4,4,5].uniq())
于 2018-02-11T06:59:36.097 回答