使用特定属性标记和删除对象数组中的重复项以进行比较

时间:2015-07-20 13:37:12

标签: arrays ruby unique

我有一个对象数组,如下所示:

[
  {
    "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["field name"] }

之类的东西

但是,对于找到的任何重复项目,最终未被删除的项目需要添加一个属性: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
  },

  .....
]

除了删除重复项之外,我还需要确保数组的顺序不受该函数的影响。

最好的方法是什么?

5 个答案:

答案 0 :(得分:1)

这是一个非常简单的解决方案:

[[UIImageView appearanceWhenContainedIn:[UpdateProfile class], nil] setImage:image];

答案 1 :(得分:1)

使用这个数组:

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
  }
]

答案 2 :(得分:0)

此版本只计算“字段名称”出现的次数,如果它大于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

答案 3 :(得分:0)

此解决方案构建一个新数组,其中排除了重复项。对于原始数组中的每个项目,它会检查是否存在已使用相同名称查看的existing项。如果是这样,它会将现有项目标记为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

答案 4 :(得分:0)

如果您使用的是Ruby v1.9 +(保证哈希值保持密钥插入顺序),您可以使用Hash#update(aka merge!)的形式使用块来确定两个哈希中存在的键的值被合并。 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}]