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]
可以从数组中删除一系列值like this:
[1, 2, 3, 4, 5, 6, 7, 8, 9].slice!(2..5)
迭代范围并应用上述相同(a2.each { |range| a1.slice!(range) }
)并不完美。范围有时会重叠,从而破坏其他范围的引用索引。
那么,有关如何以最有效的方式从a2
中移除a1
中的范围的任何建议?
a1
通常为[* 0..10080]。 a2
有大约30个范围,每个范围包含数百个值。
答案 0 :(得分:1)
如果第一次操作的结果影响第二次操作,你或者要跟踪产生的偏移影响,这可能会变得疯狂复杂,或者只是进行反向操作,而是标记你想要的或者不想使用范围:
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 :(得分:0)
我不确定这是最不天真的解决方案,但将您的范围转换为数组似乎很简单,因此您需要处理类似的问题:
a2.each{ |a| a1 = a1 - a.to_a }
答案 2 :(得分:0)
[-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]
答案 3 :(得分:0)
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)