Coffeescript / Node.js:如何从对象数组中删除重复对象?
Posted
技术标签:
【中文标题】Coffeescript / Node.js:如何从对象数组中删除重复对象?【英文标题】:Coffeescript / Node.js: How to remove duplicate objects from an array of objects? 【发布时间】:2012-11-25 22:36:48 【问题描述】:我怎样才能打开这个对象数组(其中有一些重复的对象):
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
【问题讨论】:
【参考方案1】:根据您想要检查相等性的程度,您可能只是假设 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)
【讨论】:
这可行,但通常会有不同的对象具有相同的 USERID。在实际应用中,每个对象都有 25 个属性的潜力。如果这些属性完全相同(如示例),我只想删除对象。 好吧,策略是一样的——相等性检查会变得更复杂一些。我会更新答案。 知道了。最好只是微笑和点头,然后:^)【参考方案2】:我会使用 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 的解决方案肯定是更好的解决方案,但这很可能也有效。
【讨论】:
谢谢,但我无法单独过滤 ID 上的对象。我已将对象从“用户”更改为“项目”,以帮助使问题更清晰。【参考方案3】:这是一个老问题 - 但老歌...
让我们加入数组中的对象: (将所有值放入一个数组并将其连接到一个字符串中)
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
【讨论】:
【参考方案4】:Array::uniq = ->
unique=(v, k, self) ->
self.indexOf(v)==k
@.filter(unique)
# console.log([1,2,3,3,4,4,5].uniq())
【讨论】:
虽然此代码 sn-p 可能是解决方案,但 including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。以上是关于Coffeescript / Node.js:如何从对象数组中删除重复对象?的主要内容,如果未能解决你的问题,请参考以下文章
没有 node.js 的 CoffeeScript 编译器?
CoffeeScript、Node.js、MongoDB 和 JasperReports,有可能吗?
Node.js+Express 和 CoffeeScript 的 IDE 或编辑器
无法使用 Node.js Express MongoDB Mongoose CoffeeScript 发布