2

Given an array of strings

["the" "cat" "sat" "on" "the" "mat"]

I'm looking to get all combinations of items in sequence, from any starting position, e.g.

["the"]
["the" "cat"]
["the" "cat" "sat"]
...
["cat" "sat" "on" "the" "mat"]
["sat" "on" "the" "mat"]
["on" "the" "mat"]
...
["sat" "on"]
["sat" "on" "the"]

Combinations out of the original sequence or with missing elements are disallowed, e.g.

["sat" "mat"] # missing "on"
["the" "on"]  # reverse order

I'd also like to know if this operation has a particular name or if there's a neater way of describing it.

Thanks.

3 Answers 3

6

If you're into one-liners, you might try

(0..arr.length).to_a.combination(2).map{|i,j| arr[i...j]}

BTW, I think those are called "all subsequences" of an array.

Sign up to request clarification or add additional context in comments.

3 Comments

He's asking about substrings, not subsequences. Every substring is also a subsequence, but not all subsequences are substrings. For example, 235 is a subsequence of 123456 but not a substring.
Thanks, I didn't know about the difference. So, substrings need to be consecutive elements in the original array, while subsequences don't.
In any case the above is finding the substrings, not subsequences so, just semantics...elegant solution :)
4

Just iterate over each starting position and for each starting position over each possible end position:

arr = ["the", "cat", "sat", "on", "the", "mat"]
(0 ... arr.length).map do |i|
  (i ... arr.length).map do |j|
    arr[i..j]
  end
end.flatten(1)
#=> [["the"], ["the", "cat"], ["the", "cat", "sat"], ["the", "cat", "sat", "on"], ["the", "cat", "sat", "on", "the"], ["the", "cat", "sat", "on", "the", "mat"], ["cat"], ["cat", "sat"], ["cat", "sat", "on"], ["cat", "sat", "on", "the"], ["cat", "sat", "on", "the", "mat"], ["sat"], ["sat", "on"], ["sat", "on", "the"], ["sat", "on", "the", "mat"], ["on"], ["on", "the"], ["on", "the", "mat"], ["the"], ["the", "mat"], ["mat"]]

Requires ruby 1.8.7+ (or backports) for flatten(1).

1 Comment

I took the liberty of editing the ranges to use ... instead of -1. Also note that Ruby 1.9.2 introduces flat_map which is basically equivalent to map{}.flatten(1). Also available with backports :-)
0

here you can get all the combinations

(1...arr.length).map{ | i | arr.combination( i ).to_a }.flatten(1)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.