2

I want to generate all possible consecutive word combinations of a particular string, given a minimum length as an arg.

So say I have "hello", the result would be (given a min length of 3): 'hel', 'ell', 'llo', 'hell', 'ello', 'hello'.

One way I've achieve this is via:

def get_all_word_combinations(str, min_length)
    chars = str.split('')
    all_results = []

    (min_length..str.size).each do |x|
      chars.each_cons(x) do |r|
        all_results << r.join
      end
    end
    return all_results
  end

But not sure if this would work with bigger words.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
anemaria20
  • 1,646
  • 2
  • 17
  • 36
  • @Carcigenicate sorry the ques was more about the correctness of the problem. Edited it. – anemaria20 Jan 07 '17 at 17:13
  • Flip the question: why *wouldn't* it work on bigger words? What in the code is dependent on the word length? That said, the requirements aren't clear. Are "hel" and "leh" distinct? – Dave Newton Jan 07 '17 at 17:20
  • Can't see much wrong here... maybe `get_all_word_slices` is a better name. – steenslag Jan 07 '17 at 17:44
  • What happened when you tried it with bigger words? – Jörg W Mittag Jan 07 '17 at 18:02
  • Is this related to http://stackoverflow.com/questions/41521492/faster-way-to-see-if-a-huge-list-of-strings-is-contained-within-another-string ? I'm not sure you really need all those substrings – Eric Duminil Jan 07 '17 at 20:16

1 Answers1

3

This solution avoids unnecessary joins :

word     = "hello"
size     = word.size
min_size = 3

(min_size..size).flat_map { |l| (0..size - l).map { |i| word[i, l] } }
#=> ["hel", "ell", "llo", "hell", "ello", "hello"]

If you don't need an Array but just need to iterate over every possible substring, this solution will use less memory :

(min_size..size).each do |l|
  (0..size - l).each do |i|
    # do something with word[i, l]
  end
end
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • Considering that `word = "aaaa"; size = word.size; min_size = 2; (min_size..size).flat_map { |l| (0..size - l).map { |i| word[i, l] } } #=> ["aa", "aa", "aa", "aaa", "aaa", "aaaa"]`, I suggest you tack on `.uniq`. – Cary Swoveland Jan 07 '17 at 19:08
  • @CarySwoveland : I suppose it really depends on the size of the Array and the intention of the OP. Using uniq on a huge array to remove a few substrings might not be worth it. Using `each` twice might be a better idea. – Eric Duminil Jan 07 '17 at 19:22
  • 1
    One option is to interpret the question literally: "I want to generate all possible consecutive word combinations of a particular string...". :-) – Cary Swoveland Jan 07 '17 at 20:21