46

How can I check whether one array is a subset of another array, regardless of the order of elements?

a1 = [3, 6, 4]
a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]

...?

a1 is a subset of a2
5
  • Oh, which structure. Best is probably sets, since that's what sets are good at--but as the variety of answers shows (and there are yet more options), it may not matter--depending on your needs. Commented May 12, 2012 at 21:18
  • Can there be duplicates in a1 or a2? If there can be duplicates in a1, do there have to be the same number or more duplicates in a2? In other words, what should the result be if your variables have the values a1 = [1, 1] and a2 = [1,2,3,4,5,6,7,8,9]?
    – Mark Byers
    Commented May 12, 2012 at 21:23
  • Currently I don't expect duplicates, but I imagine I would end up working with sets that contains duplicate values where I actually want to say "dupes don't matter". Would that cause an issue with arrays?
    – MxLDevs
    Commented May 12, 2012 at 21:53
  • Possible duplicate of Ruby: Array contained in Array, any order
    – Nick Roz
    Commented Sep 12, 2016 at 18:55
  • But the other way. Commented May 24, 2024 at 14:27

4 Answers 4

79

Easiest may be:

(a1 - a2).empty?
3
  • 1
    This is pure ruby and does not need require "set" Commented Jan 10, 2016 at 18:49
  • 2
    set is stdlib, so it's arguable to say that it is less pure that using list differences.
    – rewritten
    Commented Jun 13, 2016 at 14:29
  • 2
    This is the right answer, since it prevents initialization of new objects, and clogging of memory. Here only the intersect is created.
    – Algorini
    Commented Aug 24, 2018 at 18:18
42

Use sets. Then you can use set.subset?. Example:

require 'set'

a1 = Set[3,6,4]
a2 = Set[1,2,3,4,5,6,7,8,9]

puts a1.subset?(a2)

Output:

true

See it working online: ideone

1
  • 2
    Another advantage of Set is that you can also check other properties, such as proper_subset? if you didn't want identical sets to return true. Commented May 13, 2012 at 0:36
35

The data structure you already have is perfect, just check the intersection:

(a1 & a2) == a1

Update: The comment discussing permutations is interesting and creative, but quite incorrect as the Ruby implementors anticipated this concern and specified that the order of the result is the order of a1. So this does work, and will continue to work in the future. (Arrays are ordered data structures, not sets. You can't just permute the order of an array operation.)

I do rather like Dave Newton's answer for coolness, but this answer also works, and like Dave's, is also core Ruby.

5
  • 1
    Oh, just take the intersection and check. Didn't think of that lol
    – MxLDevs
    Commented May 12, 2012 at 21:18
  • I'm not certain if mine is really better, as it depends on the implemention being sort-stable. (Also on no duplicates, but the definition of the question as a set operation seems to imply that. I suppose one could sort both terms.) Commented May 12, 2012 at 21:19
  • 1
    I realize this answer is almost 4 years old, but this does not necessarily work. a1 & a2 will give a permutation of a1, which if the elements are not in the same order, will give false when comparing it == to a1. For example, a1=%w(a c); a2= %w(a b c); perm=a1&a2; (may give ['c','a']); perm==a1 => false. What is guaranteed to work is a1.permutation.include?(a1&a2).
    – istrasci
    Commented Mar 3, 2016 at 21:58
  • 1
    @istrasci, the core docs specify at ruby-doc.org/core-2.3.1/Array.html#method-i-26 that The order is preserved from the original array. This does work correctly and will continue to do so in the future as this behavior is part of the specification of the & method on Array. It's therefore also not necessary to sort the result. Commented May 16, 2016 at 21:09
  • sorry, this method is wrong, it possible a1=[1,2,3];sub_a1=[2,1];(a1&sub_a1)==a1 equal false as it need sort first then compare.
    – Eric Guo
    Commented Apr 10 at 2:15
3

Perhaps not fast, but quite readable

def subset?(a,b)
  a.all? {|x| b.include? x}
end
1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.