Arrays 使用特定属性标记并删除对象数组中的重复项以进行比较
我有一个如下所示的对象数组:Arrays 使用特定属性标记并删除对象数组中的重复项以进行比较,arrays,ruby,unique,Arrays,Ruby,Unique,我有一个如下所示的对象数组: [ { "field name" => "Account number", "data type" => "number", "mneumonic" => "ACTNUM", "field number" => "027" }, { "field name" => "Warning", "data type" => "code", "mneumonic" =>
[
{
"field name" => "Account number",
"data type" => "number",
"mneumonic" => "ACTNUM",
"field number" => "027"
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN1",
"field number" => "034:01"
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN2",
"field number" => "034:02"
},
.....
]
我需要搜索整个数组,并根据“field name”
属性标记重复项。为此,我可以使用类似于uniq{| I | I[“字段名”]}
但是,对于找到的任何重复项,最终未被删除的项需要添加一个属性:multiple=>true
。我不在乎哪一个对象最终是留在数组中的对象,只要它标记了这个属性。因此,在上面的示例中运行函数可能会产生:
[
{
"field name" => "Account number",
"data type" => "number",
"mneumonic" => "ACTNUM",
"field number" => "027",
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN1",
"field number" => "034:01",
"multiple" => true
},
.....
]
除了删除重复项之外,我还需要确保数组的顺序不受函数的影响
最好的方法是什么?这里有一个非常简单的解决方案:
array # => your array of objects
used_names = []
multiple_names = []
array.each do |hash|
name = hash['field name']
if used_names.include? name
multiple_names << name
array.delete hash
else
used_names << name
end
end
array.each do |hash|
if multiple_names.include? hash['field name']
hash['multiple'] = true
end
end
array#=>您的对象数组
已用名称=[]
多个_名称=[]
array.each do|散列|
name=hash['fieldname']
如果使用,包括哪些名称?名称
多个_名称此版本只计算“字段名称”出现的次数,如果大于1或不大于1,则根据需要更新哈希
field_name_counts = Hash.new 0
array.each do |hash|
field_name = hash["field name"]
field_name_counts[field_name] += 1
end
array.each do |hash|
field_name = hash["field name"]
if field_name_counts[field_name] > 1
hash["multiple"] = true
else
hash["multiple"] = false
end
end
使用此阵列:
a = [
{
"field name" => "Account number",
"data type" => "number",
"mneumonic" => "ACTNUM",
"field number" => "027",
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN1",
"field number" => "034:01",
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN2",
"field number" => "034:02",
},
]
此代码:
file_names = {}
a.select do
|h| k = h["field name"]
if file_names[k]
file_names[k]["multiple"] = true
false
else
file_names[k] = h
true
end
end
将提供:
[
{
"field name" => "Account number",
"data type" => "number",
"mneumonic" => "ACTNUM",
"field number" => "027"
},
{
"field name" => "Warning",
"data type" => "code",
"mneumonic" => "WARN1",
"field number" => "034:01",
"multiple" => true
}
]
此解决方案构建一个新阵列,排除重复项。对于原始数组中的每个项,它会检查是否存在已使用相同名称看到的现有
项。如果是,它将现有项标记为existing[“multiple”]=true
,并跳过该迭代
这具有在新数组中省略重复项并标记原始项的预期效果
unique_data = data.each_with_object([]) do |item, result|
if (existing = result.find { |i| i["field name"] == item["field name"] })
existing["multiple"] = true
next
end
result << item
end
unique_data=data。每个带有_对象([])的_都做|项,结果|
if(existing=result.find{| i | i[“字段名”]==item[“字段名”]})
现有[“多个”]=true
下一个
结束
结果如果您使用的是Ruby v1.9+(其中哈希保证保持键插入顺序),那么您可以使用(akamerge!
)的形式,该形式使用一个块来确定合并的两个哈希中存在的键的值a
是@sawa给出的数组
a.each_with_object({}) do |f,g|
g.update(f["field name"]=>f) { |_,h| h.merge("multiple"=>true) }
end.values
#=> [{"field name"=>"Account number", "data type"=>"number",
# "mneumonic"=>"ACTNUM", "field number"=>"027"},
# {"field name"=>"Warning", "data type"=>"code", "mneumonic"=>"WARN1",
# "field number"=>"034:01", "multiple"=>true}]
@余浩我看到你删除了我问题中提到的文件。为什么我不应该这样做呢?它只是指向Array
和Hash
参考手册的链接,可能是最常用的两个类。您也不是指某些特定的方法。任何Ruby专家都知道在哪里可以找到它们,所以我认为这不会给你的问题增加多少信息。你的数组无效。@sawa添加了逗号,很抱歉这不会删除重复项。这似乎不起作用。我想这是因为你在循环中使用了delete
,它不起作用,因为我不小心将键命名为field\u name
,而不是field name
(带有空格)。哦,您的测试数据在第一个对象中有错误(未关闭的“
,值之间没有逗号)。我已经更新并测试了答案。您是否在比我提供的数据集更大的数据集上测试了它?在每个中使用删除不会导致它跳过索引吗?迭代将继续,唯一可能不起作用的地方是当您的数组中有多个完全相同的对象时。如果是这种情况,simp只需将each
更改为each\u with\u index
,并使用delete\u at(index)
而不是delete
,这样您将只删除指定索引处的对象。