删除包含另一个数组元素的子数组

时间:2015-05-21 16:56:40

标签: arrays ruby

我有一个数组array_one,其中包含长度为K的连续子数组。我有另一个数组array_two,其中包含一些数字,至少为2.这是K = 2的示例:

array_one = [ [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7] ]
array_two = [ 4,6 ]

我想删除所有包含至少一个array_two个数的子数组,或者至少包含一个已删除的子数的子数。除了x[0]之外,所有子阵列都会被删除。

2 个答案:

答案 0 :(得分:0)

谢谢!这是一个有趣的小问题,可以分两步解决。

第一步是删除包含array_two值的项目。 第二步是生成第一步中删除的值列表,并重复相同的删除过程。

array_one = [ [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7] ]
array_two = [ 4,6 ]

array_two_removed = array_one.reject{ |e| e.any? { |v| array_two.include? v } }
values_removed = (array_one - array_two_removed).flatten.uniq # gotta love array math to make this easy
final_answer = array_two_removed.reject{ |e| e.any? { |v| values_removed.include? v } }
# loop over the array that has the first pass removed.
final_answer = array_two_removed.reject do |subarray|
  # for each sub array, see if any of the removed values exist, if so it will be removed.
  subarray.any? do |subarray_value|
    values+removed.include? subarray_value|
  end
end

答案 1 :(得分:0)

由于您的特定数据结构,您可以一次性完成此任务。

<强>假设

通过&#34;连续的子阵列&#34;我假设你的意思是,给定整数f(&#34;第一&#34;)nk

arr1 = [[f,f+1,..,f+k-1], [[f+1,f+2,..,f+k],..., [f+n-1,f+n,..,f+n+k-2]

对于你的例子:

f = 1
k = 2
n = 6

我们可以用一个提取第i个元素的方法来表示这个数组:

def stab(f,k,n,i)
  f+i..f+k-1+i
end

arr1 = n.times.map { |i| stab(f,k,n,i).to_a }
  #=> [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]] 

<强>代码

def extract(f,k,n,arr2)
   arr2.reduce(n.times.to_a) do |a,j|
     a-([j-2*k-f+2,0].max..[j+k-f-1,n-1].min).to_a
   end.map { |i| stab(f,k,n,i).to_a }
end

<强>实施例

对于你的例子:

f,k,n = 1,2,6
arr2 = [4,6]
extract(f,k,n,arr2)
  # => [[1, 2]]

有关:

f, k, n = 2, 3, 18

产生:

arr1 = n.times.map { |i| stab(f,k,n,i).to_a }
  #=> [[2, 3, 4], [3, 4, 5], [4, 5, 6], [ 5, 6, 7], [ 6, 7, 8],
  #    [7, 8, 9], [8, 9, 10], [9, 10, 11], [10, 11, 12],
  #    [11, 12, 13], [12, 13, 14], [13, 14, 15], [14, 15, 16],
  #    [15, 16, 17], [16, 17, 18], [17, 18, 19], [18, 19, 20],
  #    [19, 20, 21]] 

如果:

arr2 = [7,15]

然后:

extract(f,k,n,arr2)
  #=> [[2, 3, 4], [10, 11, 12], [18, 19, 20], [19, 20, 21]]

<强>解释

对于任何数字j,我们知道包含arr1的{​​{1}}元素的索引由范围给出:

j

(虽然我们需要确保b..e b = j-f-k+1 e = j-f b >= 0)。

对于您的示例,如果e < n,则此范围为j=4,即元素2..3

继续你的例子,考虑a = [[3,4], [4,5]]的最后一个元素的最后一个元素;也就是a5)。应用上面导出的范围4+k-1的表达式,s..e出现在5的元素中,由arr1范围内的索引给出,其中:

b..e

我们只关注范围的结束:b = 5-1-2+1 #=> 3 e = 5-1 #=> 4

现在考虑e #=> 4的第一个元素的第一个元素;也就是a3)。 4-k+1中的3元素显示在arr1范围内的索引中,b..e显示在b = 3-1-2+1 #=> 1 e = 3-1 #=> 2 中,其中:

b #=> 1

我们只关注范围的开头:arr1

我们现在已经确定,对于该示例,包含arr1的任何元素的至少一个元素的4元素的索引由下式给出:范围:

1..4

我们留下:

stab(1,2,6,0).to_a #=> [1,2]

stab(1,2,6,5).to_a #=> [6,7]

更一般地说,对于整数j,此范围由下式给出:

(j-k+1)-f-k+1..(j+k-1)-f

简化为:

j-2*k-f+2..j+k-f-1

但是,我们需要确保第一个索引是非负数且最后一个指数小于n

[j-2*k-f+2,0].max..[j+k-f-1,n-1].min

例如,这告诉我们如果j=4,我们可以在索引处删除arr的元素:

[4-2*2-1+2,0].max..[4+2-1-1,5].min
  #=> 1..4

如果j=6,我们可以使用索引中的元素:

[6-2*2-1+2,0].max..[6+2-1-1,5].min
  #=> 3..6

只留下arr1[0] #=> [1,2]

因此,您可以按如下方式获得所需的结果:

def extract(f,k,n,arr2)
   arr2.reduce(n.times.to_a) do |a,j|
     a-([j-2*k-f+2,0].max..[j+k-f-1,n-1].min).to_a
   end.map { |i| stab(f,k,n,i).to_a }
end

arr2 = [4,6] 
extract(1,2,6,arr2)
  #=> [[1,2]]

现在考虑我用于上面第二个例子的arr1,它由以下参数指定:

f, k, n = 2, 3, 18

假设:

arr2 = [7,15]

然后

extract(f,k,n,arr2)
  #=> [[2, 3, 4], [10, 11, 12], [18, 19, 20], [19, 20, 21]]

<强>讨论

这个答案可能类似于用锤子拍苍蝇。我提供它有两个原因。第一个是因为我认为您可能想要考虑通过三个参数在应用程序中表示数组arr1。如果数组非常大,那么这可能很有用,因为可以使用方法stab根据需要构造元素。第二个原因仅仅是解决问题的挑战。