从散列数组中过滤值并从原始数组中删除它们

Gab*_*ger 2 ruby arrays hash select

我正在努力寻找过滤散列数组的正确方法,删除与过滤条件匹配的条目,同时返回这些已删除的散列。这是一个例子,magic_function!它完成了我想要实现的目标:

my_array = [{ id: 1, val: 'foo' }, { id: 2, val: 'bar' }, { id: 3, val: 'baz' }]

extracted_hashes = my_array.magic_function! { |hash| hash[:id] == 1 }
# [{ id: 1, val: 'foo' }]

my_array
# [{ id: 2, val: 'bar' }, { id: 3, val: 'baz' }]

Run Code Online (Sandbox Code Playgroud)

我尝试这样做的原因是因为该数组是一个庞大的数据库行集合,我需要使用另一个 ID 数组中的值来处理它们。(不幸的是,该部分无法更改,限制来自数据库的行会更有效率)

使用Array.filter允许我获取正确的哈希值,但每次都在数组的整个长度上进行迭代。由于我不需要已经处理过的散列,我假设从原始数组中删除它们会使它变得越来越小,从而减少过滤下一个 ID 所需的迭代量,直到所有 ID 都已处理完毕并且有原始数组中没有任何剩余。

Tim*_*and 8

用于partition根据过滤条件将输入数组分成 2 个数组。您也可以修改输入数组,方法是在赋值的左侧使用它:

my_array = [{ id: 1, val: 'foo' } , { id: 2, val: 'bar' } , { id: 3, val: 'baz' }]

# split input array into 2 new arrays, keep input array as is:
selected, other = my_array.partition { |hash| hash[:id] == 1 }

puts "#{selected}"   # [{:id=>1, :val=>"foo"}]
puts "#{other}"      # [{:id=>2, :val=>"bar"}, {:id=>3, :val=>"baz"}]


# remove from the input array selected elements into 1 new array,
# keep the rest in the input array (change the input array in-place):
selected, my_array = my_array.partition { |hash| hash[:id] == 1 }

puts "#{selected}"  # [{:id=>1, :val=>"foo"}]
puts "#{my_array}"  # [{:id=>2, :val=>"bar"}, {:id=>3, :val=>"baz"}]

Run Code Online (Sandbox Code Playgroud)

请注意,partition可以在单个操作中将其视为selectreject(或filterreject)。这是一个简单的例子来说明什么partition

x, y = [3, 2, 1, 4].partition { |n| n < 3 }
puts "#{x}; #{y}"   # [2, 1]; [3, 4]
Run Code Online (Sandbox Code Playgroud)