'string' to ['s', 'st', 'str', 'stri', 'strin', 'string']

What's the most elegant way of doing

'string'
=> ['s', 'st', 'str', 'stri', 'strin', 'string']

I've been trying to think of a one liner, but I can't quite get there. Any solutions are welcome, thanks.

You can use Abbrev in Standard Library

require 'abbrev'
s = Abbrev::abbrev(['string']).keys
puts s.inspect

I must add the other way to use this after requiring the Abbrev library, with the .abbrev method added to Array:

require 'abbrev'
s = ['string'].abbrev.keys
puts s.inspect

If the order is important to match your return in the question, just call .sort on keys.

How about this?

s = 'string'
res = s.length.times.map {|len| s[0..len]}
res # => ["s", "st", "str", "stri", "strin", "string"]

The more declarative I can come up with:

s = "string"
1.upto(s.length).map { |len| s[0, len] } 
#=> ["s", "st", "str", "stri", "strin", "string"]

s.chars.zip.inject{ |i,j| i << i.last + j.first }

Comments
  • @user21033168, sorry, but interesting as it is to know about this library (personally I didn't know it, thanks @vgoff) I don't see how a solution that requires using sort and intermediate objects should be selected instead of any of ther others which do a simple map, for example Sergio's.
  • @tokland I actually didn't need .sort, so I just liked the shortness of this solution with %w{string}.abbrev.keys :)
  • fair enough, though it will be a bit misleading for future SO readers looking for the exact thing what you asked, the "inits" (as Haskell calls it) of a string in Ruby.
  • I was unsure if you actually needed sort, or just the member elements needed to be identical. Sort is only here for ease of human reading of return.
  • @Sergio. Yeah, I saw, apparently a simple map is forbidden to implement this. Whatever.
  • It wasn't me who downvoted either of you, they're fine solutions :)
  • @user21033168: I figured, don't worry ;-)
  • In fact, this approach (almost) is used by abbrev to split the string.
  • This is actually my favourite solution, because it doesn't refer back to s in the method chain and it's clever.
  • This produces an empty string as first result.
  • I get ["", "s", "st", "str", "stri", "strin", "string"] in Ruby 1.9. A bit convoluted in any case.