views:

46

answers:

1

I'm looking to find all combinations of single items from a variable number of arrays. How do I do this in Ruby?

Given two arrays, I can use Array.product like this:

groups = []
groups[0] = ["hello", "goodbye"]
groups[1] = ["world", "everyone"]

combinations = groups[0].product(groups[1])

puts combinations.inspect 
# [["hello", "world"], ["hello", "everyone"], ["goodbye", "world"], ["goodbye", "everyone"]]

How could this code work when groups contains a variable number of arrays?

+4  A: 
groups = [
  %w[hello goodbye],
  %w[world everyone],
  %w[here there]
]

combinations = groups.first.product(*groups.drop(1))

p combinations
# [
#   ["hello", "world", "here"],
#   ["hello", "world", "there"],
#   ["hello", "everyone", "here"],
#   ["hello", "everyone", "there"],
#   ["goodbye", "world", "here"],
#   ["goodbye", "world", "there"],
#   ["goodbye", "everyone", "here"],
#   ["goodbye", "everyone", "there"]
# ]
Jörg W Mittag
Wow, thank you. Could you, or someone, possibly explain how this works?
Ollie G
An explanation of what this actually does would be helpful too, and probably lead to better design of the OP's code...
jtbandes
@Ollie: `Array#product` can take multiple arrays as arguments, so this is just basically doing `groups[0].product(groups[1],groups[2],...)`
jtbandes
How it works: `product` takes however many arrays you apply to it and gives the Cartesian product of the receiver and all the arguments. The splat operator "expands" an array into a list of arguments, so we take all the arrays in `groups` except the first and pass them as arguments to `product`.
Chuck
Brilliant, thanks everyone.
Ollie G
i heart ruby-lang.
Jed Schneider