如何检查另一个数组是否是另一个数组的子序列?

时间:2014-06-04 18:53:08

标签: ruby

我有两个阵列;其中一个b可能是另一个的一部分,a;如何检查b是否为a

的子序列

基本上,[3, 4, 5]将是(1..10).to_a的子序列,但不是(1..10).to_a.shuffle

8 个答案:

答案 0 :(得分:3)

a = [1,2,3]
b = (1..10).to_a

a_sorted = a.sort
b.each_cons(a.size).any?{ |c| c.sort == a_sorted }

原始解决方案

b.each_cons(a.size).any?{ |c| c == a }

答案 1 :(得分:2)

使用Enumerable连续迭代

arr = [1,2,3]
(1..10).to_a.each_cons(arr.size).include? arr
# => true

arr = [1,3,2]
(1..10).to_a.each_cons(arr.size).include? arr
# => false

答案 2 :(得分:1)

您可以对潜在子集的每个元素使用Enumerable的#find_index方法,并确保索引在潜在超集中的顺序相同。

试试这个:

a = (1..10).to_a
b = [3,4,5]
# Use #compact to remove all nils
b_indices = b.map {|x| a.find_index(x)}.compact
b_indices == b_indices.sort # use #sort to ensure ordering

答案 3 :(得分:0)

答案 4 :(得分:0)

也许不是最优雅的解决方案,但应该可以肯定。 简单的蛮力:

def substring?(a, b)
  position = 0
  a.each_with_index do |v, i|
    if v == b[position] and (i + b.size - position) <= a.size
      position += 1
    elsif position == b.size
      return true
    else
      position = 0
    end
  end

  position == b.size
end

其中 b 是您的数组, a 是候选子集。

答案 5 :(得分:0)

这是另一种方式。这个解决方案符合我对问题的理解,但它可能不是提问者的想法。看看我对这个问题的评论。 (编辑:在澄清问题时,这不是提问者想要的,但我会留下它可能的教育价值。)

<强>代码

def subsequence?(a,b)
  c = b.map.with_index.to_h.values_at(*a)
  return false if c.any?(&:nil?)
  c == c.sort
end

<强>实施例

subsequence?([3,4,5], (1..10).to_a)         #=> true
subsequence?([3,5,4], (1..10).to_a)         #=> false
subsequence?([3,4,5], (1..10).to_a.reverse) #=> false
subsequence?([3,4,5], [1,2,3,4,6])          #=> false
subsequence?([3,4,5], [3,4,2,5])            #=> true

<强>解释

计算后

c = b.map.with_index.to_h.values_at(*a)

c.any?(&:nil?)

确定b是否包含a的所有元素。如果是的话

c == c.sort

检查它们是否处于相同的顺序。

示例1

a = [3,4,5]
b = (1..10).to_a

然后

d = b.map.with_index.to_h
  #=> {1=>0, 2=>1, 3=>2, 4=>3, 5=>4, 6=>5, 7=>6, 8=>7, 9=>8, 10=>9}
c = d.values_at(*a)
  #=> [2, 3, 4]
c.any?(&:nil?)
  #=> false

因此,我们看到a中包含b的值,我们需要查看它们是否按顺序排列:

c == c.sort
  #=> [2, 3, 4] == [2, 3, 4]
  #=> true

示例2

a = [3,5,4]
b = (1..10).to_a

然后

d = b.map.with_index.to_h
  #=> {1=>0, 2=>1, 3=>2, 4=>3, 5=>4, 6=>5, 7=>6, 8=>7, 9=>8, 10=>9}
c = d.values_at(*a)
  #=> [2, 4, 3]
c.any?(&:nil?)
  #=> false

所以我们再次需要看看它们是否有序:

c == c.sort
  #=> [2, 4, 3] == [2, 3, 4]
  #=> false

示例3

a = [3,5,4]
b = (1..10).to_a.reverse

然后

d = b.map.with_index.to_h
  #=> {10=>0, 9=>1, 8=>2, 7=>3, 6=>4, 5=>5, 4=>6, 3=>7, 2=>8, 1=>9}
c = d.values_at(*a)
  #=> [7, 5, 6]
c.any?(&:nil?)
  #=> true
c == c.sort
  #=> false

示例4

a = [3,5,4]
b = [1,2,3,4,6]

然后

d = b.map.with_index.to_h
  #=> {1=>0, 2=>1, 3=>2, 4=>3, 6=>4}
c = d.values_at(*a)
  #=> [2, nil, 3]
c.any?(&:nil?) 
  #=> true

示例5

a = [3,4,5]
b = [3,4,2,5]

然后

d = b.map.with_index.to_h
  #=> {3=>0, 4=>1, 2=>2, 5=>3}
c = d.values_at(*a)
  #=> [0, 1, 3]
c.any?(&:nil?)
  #=> false
c == c.sort
  #=> true

又一个解决方案

def subsequence?(a,b)
  ([a] & b.combination(a.size).to_a).any?
end

答案 6 :(得分:0)

还有一个。这个解决方案符合我对问题的理解,但它可能不是提问者的想法。看看我对这个问题的评论。 (编辑:在澄清问题时,这不是提问者想要的,但我会留下它可能的教育价值。)

<强>代码

def subsequence?(a,b)
  enum_a = a.each
  enum_b = b.each
  loop do
    av = enum_a.next
    loop do
      begin
        bv = enum_b.next
        break if (av == bv)
      rescue StopIteration
        return false
      end
    end  
  end    
  true
end 

<强>实施例

subsequence?([3,4,5], (1..10).to_a)         #=> true
subsequence?([3,5,4], (1..10).to_a)         #=> false
subsequence?([3,4,5], (1..10).to_a.reverse) #=> false
subsequence?([3,4,5], (1..10).to_a.reverse) #=> false
subsequence?([3,4,5], [1,2,3,4,6])          #=> false
subsequence?([3,4,5], [3,4,2,5])            #=> true

答案 7 :(得分:0)

非常简单有效的方法(不是零安全):

leftovers = array.reduce(sub) { |a, e| e == a[0] ? a[1..-1] : a }
puts "sub is subsequence of array!" if leftovers.empty?

请参阅:https://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-reduce