ruby on rails-从数组中删除多个值范围


a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
a2 = [2..4, 8..11, 16..17]

从数组中删除一个值范围可以这样做:

[1, 2, 3, 4, 5, 6, 7, 8, 9].slice!(2..5)

不过,在这些范围内迭代并应用与上述相同的方法(a2.each { |range| a1.slice!(range) }(并不完美。这些范围有时会重叠,从而破坏其他范围的引用索引。

那么,关于如何以最有效的方式从a1中删除a2中的范围,有什么建议吗?a1通常为[*0..10800]长。a2具有大约30个范围,每个范围包含数百个值。

如果第一次运算的结果影响了第二次运算,你要么必须跟踪由此产生的偏移影响,这可能会变得非常复杂,要么只是进行反向运算,转而使用范围标记你想要或不想要的:

require 'set'
a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
a2 = [2..4, 8..11, 16..17]
# Convert the ranges to a set of index values to remove
reject = Set.new(a2.flat_map(&:to_a))
# Using value/index pairs, accumulate those values which are
# not being excluded by their index.
a1.each_with_index.each_with_object([ ]) do |(v, i), a|
  a << v unless (reject.include?(i))
end
# => [0, 1, 5, 6, 7, 12, 13, 14, 15, 18, 19, 20]
[-1, *a2.flat_map(&:minmax), a1.length].each_slice(2).flat_map{|i,j| a1[i+1...j]}
# => [0, 1, 5, 6, 7, 12, 13, 14, 15, 18, 19, 20] 

我不确定这是最简单的解决方案,但将范围转换为数组似乎很简单,因此您可以处理同类:

a2.each{ |a| a1 = a1 - a.to_a }
a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
a2 = [2..4, 8..11, 16..17]
a1 - a2.flat_map(&:to_a)

最新更新