ruby 在哈希中删除相同的值多个键

Posted

技术标签:

【中文标题】ruby 在哈希中删除相同的值多个键【英文标题】:ruby remove same value multiple keys in hash 【发布时间】:2014-06-05 23:48:11 【问题描述】:

来自以下哈希

hash ="a"=>100,"b"=>200,"c"=>100,"d"=>120,"e" => 400, "f"=>430, "g"=>500

我想删除所有具有相同“值”或差异为 50(“值”)的对(“键”、“值”)。 例如,a=>100 和 c => 100,应该被删除,因为它们具有相同的“值”。并且 d=>120 也应该被删除,因为 100 和 120 之间的差异是 20。400 和 430 也应该被删除,因为差异是 30。

我应该只有

哈希["b"=>200,"g"=>500]

以上只是一个示例,实际上,我有 33,000 个键的哈希值。

【问题讨论】:

"e"=>180 意味着生成的哈希应该是空的? 相差50?从什么值?应该保留哪个具有相同值的键?这么多问题... 是的,“e”=>180,表示哈希为空 @squiguy 我编辑了这个问题。我希望它现在清楚 这个问题从我第一次看的时候就真的变了。这完全不是我第一次读到的。 【参考方案1】:

如果(v1-v2).abs <= 50,一对哈希的键/值对k1=>v1k2=>v2都将被删除。这包括 v1 == v2 的对,因此我们不需要单独考虑后者。为此,我首先构造一个要保留的键数组,然后创建一个由原始哈希中的相应键/值对组成的哈希。

代码

keys_to_keep = hash.keys -
  hash.sort_by  |_,v| v 
      .each_cons(2)
      .each_with_object([]) 
        |((k1,v1),(k2,v2)),a| a << k1 << k2 if (v1-v2).abs <= 50 

keys_to_keep.zip(hash.values_at(*keys_to_keep)).to_h

说明

hash = "a"=>100,"b"=>200,"c"=>100,"d"=>120

按哈希值排序:

b = hash.sort_by  |_,v| v 
  #=> [["a", 100], ["c", 100], ["d", 120], ["b", 200]]

接下来,使用Enumerable#each_cons构造一个包含b的所有相邻元素对的数组:

c = b.each_cons(2)
  #=> #<Enumerator:
  # [["a", 100], ["c", 100], ["d", 120], ["b", 200]]:each_cons(2)>

查看这个枚举器的内容:

c.to_a
  #=> [[["a", 100], ["c", 100]],
  #    [["c", 100], ["d", 120]],
  #    [["d", 120], ["b", 200]]]

现在构建一个由要删除的键组成的数组(重复确定)

d = c.each_with_object([]) 
  |((k1,v1),(k2,v2)),a| a << k1 << k2 if (v1-v2).abs <= 50 
  #=> ["a", "c", "c", "d"]

要计算 d,请考虑由枚举器 c 传递给块的第一个值:

k1 => "a"
v1 => 100
k2 => "c"
v2 => 100

自从

(100 - 100).abs <= 50

k1k2 被添加到要删除的键数组中(块变量 a)。传递给块的下一个值是:

k1 => "c"
v1 => 100
k2 => "d"
v2 => 120

自从

(100 - 120).abs <= 50

"c""d" 键也添加到 a。第三个值不会向a 添加任何键,因为

(120 - 200).abs > 50

现在使用 set Difference 构造一个要保留的键数组:

e = hash.keys
  #=> ["a", "b", "c", "d"]

keys_to_keep = e - d
  #=> ["b"]

提取要保留的键的值,使用Hash#values_at:

f = hash.values_at(*keys_to_keep)
  #=> [200]

为要保留的键构造一个键/值对数组:

g = keys_to_keep.zip(f)
  #=> [["b", 200]]

转换为哈希。

g.to_h # Ruby v.2.0+
  #=> "b"=>200

Hash[g]
  #=> "b"=>200

【讨论】:

【参考方案2】:

试试这个:

multiple_values = hash.group_by  |k, v| v .select  |v, i| i.length > 1 .map  |v, i| v 

hash.delete_if  |k, v| multiple_values.any?  |i| v < i + 50 && v > i - 50  

第一行为所有值构建一个直方图(按值对条目进行分组),并过滤掉所有只有一个条目的值。 这为我们提供了与多个键关联的所有值的列表。 第二遍删除所有值接近其中一个小于 50 的键。

【讨论】:

你能解释一下吗?我认为它正在构建一个直方图,然后将其中的重复项放入多个值中,但我不确定我是否正确。 @Sqeaky - 你是对的。我试图澄清解释。 @UriAgassi 我已经编辑了我的问题。你能帮我修一下吗?当前解决方案查找重复值,然后使用 +/-50 窗口。在任何情况下,我都需要查看 +/-50。

以上是关于ruby 在哈希中删除相同的值多个键的主要内容,如果未能解决你的问题,请参考以下文章

Cassandra 的哈希值是不是跨多个表具有相同的值?

Ruby on Rails:删除多个哈希键

哈希表中的条目是否可以使用相同的键和相同的值?

汇总所有相似哈希键的值 Ruby

C#使用多个键为相同的值启用枚举

如果值相同,则连接哈希键,如果键相同,则连接哈希值