I have two arrays; one of them, b, is probably a subset of the other, a; how can I check if b is a subsequence of a?
Basically, [3, 4, 5] would be a subsequence of (1..10).to_a, but not (1..10).to_a.shuffle.
I have two arrays; one of them, b, is probably a subset of the other, a; how can I check if b is a subsequence of a?
Basically, [3, 4, 5] would be a subsequence of (1..10).to_a, but not (1..10).to_a.shuffle.
 
    
    a = [1,2,3]
b = (1..10).to_a
a_sorted = a.sort
b.each_cons(a.size).any?{ |c| c.sort == a_sorted }
And original solution
b.each_cons(a.size).any?{ |c| c == a }
 
    
    Using Enumerable each consecutive to iterate
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
 
    
     
    
    You could use Enumerable's #find_index method with each element of the potential subset and ensure that the indices are in the same order in the potential superset.
Try this:
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
 
    
    Very simple and effective approach (not nil-safe):
leftovers = array.reduce(sub) { |a, e| e == a[0] ? a[1..-1] : a }
puts "sub is subsequence of array!" if leftovers.empty?
See: https://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-reduce
You can use either Set or Array's default methods. 
For Array look at it:
How can I get the intersection, union, and subset of arrays in Ruby?
For Set: http://www.ruby-doc.org/stdlib-2.1.2/libdoc/set/rdoc/Set.html
Maybe not the most elegant solution, but should work for sure. Simple brute force:
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
where b is your array and a is a candidate subset.
 
    
     
    
    Here's another way. This solution conforms with my understanding of the problem, but it may not be what the asker had in mind. See my comments on the question. (Edit: upon clarification of the question, it is not what the asker wanted, but I'll leave it up for its possible educational value.)
Code
def subsequence?(a,b)
  c = b.map.with_index.to_h.values_at(*a)
  return false if c.any?(&:nil?)
  c == c.sort
end
Examples
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
Explanation
After computing
c = b.map.with_index.to_h.values_at(*a)
c.any?(&:nil?)
determines whether b contains all the elements of a. If it does
c == c.sort
checks to see if they are in the same order.
Example 1
a = [3,4,5]
b = (1..10).to_a
then
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
So we see the values of a are contained in b, we need to see if they are in order:
c == c.sort
  #=> [2, 3, 4] == [2, 3, 4]
  #=> true
Example 2
a = [3,5,4]
b = (1..10).to_a
then
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
so again we need to see if they are in order:
c == c.sort
  #=> [2, 4, 3] == [2, 3, 4]
  #=> false
Example 3
a = [3,5,4]
b = (1..10).to_a.reverse
then
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
Example 4
a = [3,5,4]
b = [1,2,3,4,6]
then
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
Example 5
a = [3,4,5]
b = [3,4,2,5]
then
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
Yet another solution
def subsequence?(a,b)
  ([a] & b.combination(a.size).to_a).any?
end
 
    
    One more. This solution conforms with my understanding of the problem, but it may not be what the asker had in mind. See my comments on the question. (Edit: upon clarification of the question, it is not what the asker wanted, but I'll leave it up for its possible educational value.)
Code
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 
Examples
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
