/ Tags: RUBY-CODE / Categories: SOLUTIONS

Generate All Combinations Of Array Elements Without Repetition In Ruby

Picking every possible pair of players, every three-item bundle from a catalogue, every subset of feature flags — these are combinations, and Ruby has them built in. No manual nested loops required.

Description

combination(n) yields every unordered selection of n elements. Order doesn’t matter, so [1, 2] and [2, 1] count as the same combination and only one appears. permutation(n) is the ordered version, where [1, 2] and [2, 1] are both produced. Use combination for teams and subsets, permutation for orderings and arrangements. Both return an Enumerator when called without a block, so .to_a materializes them and .lazy lets you take the first few without generating all of them — which matters, because the counts grow fast.

Sample input:

  [:a, :b, :c, :d].combination(2).to_a


Sample Output:

  # => [[:a, :b], [:a, :c], [:a, :d], [:b, :c], [:b, :d], [:c, :d]]

Answer

  items = [:a, :b, :c, :d]

  items.combination(2).to_a
  # => [[:a,:b], [:a,:c], [:a,:d], [:b,:c], [:b,:d], [:c,:d]]

  items.combination(3).to_a
  # => [[:a,:b,:c], [:a,:b,:d], [:a,:c,:d], [:b,:c,:d]]

  # Every possible subset, including empty and full
  (0..items.size).flat_map { |n| items.combination(n).to_a }
  # => [[], [:a], [:b], ..., [:a,:b,:c,:d]]

  # Ordered arrangements instead
  items.permutation(2).to_a
  # => [[:a,:b], [:b,:a], [:a,:c], ...]

  # Combinations across two different arrays
  [:small, :large].product([:red, :blue])
  # => [[:small,:red], [:small,:blue], [:large,:red], [:large,:blue]]

  # Lazy — don't build 2_598_960 hands to look at three
  (1..52).to_a.combination(5).lazy.first(3)

  # Count without generating
  def n_choose_k(n, k) = (1..k).reduce(1) { |acc, i| acc * (n - i + 1) / i }
  n_choose_k(52, 5)   # => 2598960

Learn More

cdrrazan

Rajan Bhattarai

Full Stack Software Developer! 💻 🏡 Grad. Student, MCS. 🎓 Class of '23. GitKraken Ambassador 🇳🇵 2021/22. Works with Ruby / Rails. Photography when no coding. Also tweets a lot at TW / @cdrrazan!

Read More