Ruby 更快地删除数组散列中的值

Ruby 更快地删除数组散列中的值,ruby,hash,Ruby,Hash,我有以下散列: new_hash = { [1] => [2, 3, 4, 7, 8 ], [2] => [3, 5], [3] => [5, 6, 7, 8, 9, 10], [4] => [], } 我想选择元素数最多的键,即第三个键 我试过: selected_user = new_hash.max_by{|k,v| v.length}.first 在找到包含最多元素的键之后,我想删除所有其他元素中的值。我想要的结果是: new_hash

我有以下散列:

new_hash = {
  [1] => [2, 3, 4, 7, 8 ],
  [2] => [3, 5],
  [3] => [5, 6, 7, 8, 9, 10],
  [4] => [],
}
我想选择元素数最多的键,即第三个键

我试过:

selected_user = new_hash.max_by{|k,v| v.length}.first   
在找到包含最多元素的键之后,我想删除所有其他元素中的值。我想要的结果是:

new_hash = {
  [1] => [2, 3, 4],
  [2] => [3],
  [3] => [5, 6, 7, 8, 9, 10],
  [4] => [],
}
我尝试使用数组删除所有重复项,方法是将值放入数组,然后删除2D数组中的所有元素

for a in 0..new_arr.length-1
    new_arr[a] = new_arr[a] - newer_arr
end
这是可行的,但是大型散列的速度非常低。如何提高此操作的速度

new_hash = { [1] => [2, 3, 4, 7, 8 ], [2] => [3, 5], [3] => [5, 6, 7, 8, 9, 10], [4] => [], }

selected_user = new_hash.max_by{|k,v| v.length}.first

selected_values = new_hash[selected_user]

new_hash.each do |k, v|
  next if k == selected_user
  new_hash[k] = v - selected_values
end

puts new_hash
运行时:

{[1]=>[2, 3, 4], [2]=>[3], [3]=>[5, 6, 7, 8, 9, 10], [4]=>[]}
这样做:

selected_user_key = new_hash.max_by{|k,v| v.length}.first    

# I suggest to use dup to not alter the original new_hash
return_hash = new_hash.dup

# Step 1 - remove the element from the hash
elements_of_selected_user = return_hash.delete(selected_user_key)

# Step 2 - remove the items that are in elements_of_selected_user
return_hash = Hash[return_hash.map{|k,v| [k, v - elements_of_selected_user]}]

# Step 3 - add the element back to the hash
return_hash[selected_user_key] = elements_of_selected_user
这是因为在Ruby中可以执行数组操作,例如
-

[1,2,3] - [2] == [1, 3]
单向:

key, value = new_hash.max_by { |_,a| a.size }
new_hash.merge(new_hash) { |_,v| v - value }.update(key=>value)
  #=> {[1]=>[2, 3, 4], [2]=>[3], [3]=>[5, 6, 7, 8, 9, 10], [4]=>[]}
这使用了使用块的形式

{ |_,v| v - value }
确定合并哈希中每个键的值


如果两个键的数组大小与其值相同,那么结果当然取决于键的顺序(Ruby v1.9+)

很有可能是数组而不是散列让你慢下来了

当您使用
[1,2,3]-[1,2]
时,您正在创建第三个数组,并且当您迭代散列时,创建越来越多的对象会调用内存分配,这会降低您的速度

如果您知道数组的所有成员都是唯一的,我建议您使用集合而不是数组,利用该方法

require 'set'
new_hash = {
  [1] => [2, 3, 4, 7, 8 ].to_set,
  [2] => [3, 5].to_set,
  [3] => [5, 6, 7, 8, 9, 10].to_set,
  [4] => [].to_set,
}

selected_user = new_hash.max_by{|k,v| v.length}.first
values = new_hash[selected_user]
new_hash.each {|k, v| v.subtract values unless k == selected_user}
由于内存分配和对象管理的不同,Set对象的创建稍微慢一些,但是由于您没有使用此过程创建新对象,因此它应该稍微高效一些,特别是对于大型持久数据结构

附言

在用户id密钥中使用数组有什么原因吗?散列键是冻结的,无法更改,因此我看不到使用数组的附加值(与FixNum相比,这会降低速度)

为什么不使用:

require 'set'
new_hash = {
  1 => [2, 3, 4, 7, 8 ].to_set,
  2 => [3, 5].to_set,
  3 => [5, 6, 7, 8, 9, 10].to_set,
  4 => [].to_set,
}