1

I'm trying to achieve:

'abc'.scan(regex) #=> ['a', 'b', 'c', 'ab', 'bc', 'abc']

It can be done like this:

(1..'abc'.size).map {|l| 'abc'.scan /(?=(\w{#{l}}))/}.flatten
#=> ["a", "b", "c", "ab", "bc", "abc"]

But I would like to do it in one regex expression.

sawa
  • 165,429
  • 45
  • 277
  • 381
Asone Tuhid
  • 539
  • 4
  • 13

1 Answers1

3

What about without regex?:

string = 'abc'
p (1..string.size).flat_map { |e| string.chars.each_cons(e).map(&:join) }
# ["a", "b", "c", "ab", "bc", "abc"]
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
  • This works, but `each_cons` eventually gets called with `4` in this example, which is too high. You should modify the code to use `(1..string.size)` and `each_cons(e)` instead. I also suggest renaming `|e|` to `|substr_length|` for clarity. – Rory O'Kane Jan 23 '18 at 17:28
  • `combination(e)` instead of `each_cons(e)` works too. – Sagar Pandya Jan 23 '18 at 17:39
  • 2
    @SagarPandya That includes "ac". – Stefan Pochmann Jan 23 '18 at 18:14
  • Very minor: I suggest `each_char` rather than `chars` to avoid an unneeded temporary array. – Cary Swoveland Jan 23 '18 at 18:59
  • No, what I'm interested in is if there is a method or a Regex functionality to find overlapping matches of all possible lengths – Asone Tuhid Jan 23 '18 at 20:30
  • 2
    Asone, you certainly cannot do that with a single regex combined with a method like `String#scan`. Regular expressions are simply not designed to do that sort of thing. With regards to a "method" that does that, do you mean a built-in method? (After all Sebatian could wrap what he has in a method.) If you mean a built-in method, it would have to be an instance method of the class `String`. Go through those methods and you won't find any that even come close to what you want to do. – Cary Swoveland Jan 24 '18 at 08:06
  • @CarySwoveland thanks, that's exactly what I was asking (It's really more of a regex question than a ruby question). It's a shame there's no nicer way to do it. – Asone Tuhid Jan 24 '18 at 11:24