Idiomatic way to get array of possible slices from string

D

drKreso

I am interesed in Ruby idiomatic way to get array of all possible
slices of particular string. For example
if I have string "hello" i would like to get

["hello", "ello", "llo", "lo", "o", "default"]

and a "default" on the end... This is what I came up with but it
doesn't feel right.

# all possible keys
# ex. for 211 keys are [211,11,1,"default"]
def keys
result = []
amount_as_string = @amount.to_s
while(amount_as_string != "")
result << amount_as_string.to_i
amount_as_string.slice!(0)
end
result << "default"
end

Help would be appreciated.

Best Regards

Kresimir Bojcic

www.kresimirbojcic.com
 
S

Simon Krahnke

* drKreso said:
I am interesed in Ruby idiomatic way to get array of all possible
slices of particular string. For example
if I have string "hello" i would like to get

["hello", "ello", "llo", "lo", "o", "default"]

Your example doesn't fit the specification. For example, "hell", "ell",
"ll" are also splices of "hello", as well as all the single letters.
and a "default" on the end...

Why is that?
This is what I came up with but it doesn't feel right.

Above you do strings, here so deal only with the string representation
of a number, and feed numbers in your result array.
# all possible keys
# ex. for 211 keys are [211,11,1,"default"]
def keys
result = []
amount_as_string = @amount.to_s
while(amount_as_string != "")
result << amount_as_string.to_i
amount_as_string.slice!(0)
end
result << "default"
end

That would certainly return something like your example.

To produce something like the specification says, I would try:

def all_splices s
len = s.length
r = []
(0..len-1).each do | i |
(1..(len-i)).each do | l |
r << s[i, l]
end
end
r << "default"
end

Untested, so certainly wrong.

mfg, simon .... l
 
D

drKreso

Thanks. I am building an inflector for certain words. For example
week. (In Croatian it is not so simple).
So you have(week = tjedan):

tjedan:
default: tjedana
1: tjedan
2: tjedna
3: tjedna
4: tjedna
11: tjedana
12: tjedana
13: tjedana
14: tjedana

Now if i have 21 for example i try to find 21 in my hash. If no direct
hit is found I look for 1 and decide it is 21 tjedan.
If I have 2014 I look for 2014 - nothing, then 014 - nothing, then 14
and i decide it is 2014 tjedana.
If I have 77 I look for 77 - nothing, then I look for 7 - nothing, and
I decide it is 77 tjedana (default).
So I don't need all the slices, just the one in the example and then I
use that array to do "match"


# first non nil match wins, there is guaranteed to be at least one
(default)
def inflected
keys.map { |key| @unit_inflections[key] }.compact[0]
end

Still I suspect there is more elegant way that to use while

* drKreso said:
I am interesed in Ruby idiomatic way to get array of all possible
slices of particular string. For example
if I have string "hello" i would like to get
["hello", "ello", "llo", "lo", "o", "default"]

Your example doesn't fit the specification. For example, "hell", "ell",
"ll" are also splices of "hello", as well as all the single letters.
and a "default" on the end...

Why is that?
This is what I came up with but it doesn't feel right.

Above you do strings, here so deal only with the string representation
of a number, and feed numbers in your result array.
# all possible keys
 # ex. for 211 keys are [211,11,1,"default"]
 def keys
   result = []
   amount_as_string = @amount.to_s
   while(amount_as_string != "")
     result << amount_as_string.to_i
     amount_as_string.slice!(0)
   end
   result << "default"
 end

That would certainly return something like your example.

To produce something like the specification says, I would try:

def all_splices s
  len = s.length
  r = []
  (0..len-1).each do | i |
    (1..(len-i)).each do | l |
      r << s[i, l]
    end
  end
  r << "default"
end

Untested, so certainly wrong.

mfg,                   simon .... l
 
D

drKreso

After playing with each_cons (that seemed promising but I was unable
to put it together) I've noticed good old take.
So I've ended up with this:

# all possible keys
# ex. for 211 keys are [211,11,1,"default"]
def keys
(1..amount_as_array.size).inject(["default"]) { |result,n| result
<< amount_as_array.take(n).join.reverse.to_i }.reverse
end

def amount_as_array
@amount.to_s.split(//).reverse
end

This seems much more idiomatic, not to mention while is almost a code
smell :)

Kresimir Bojcic

www.kresimirbojcic.com
 
R

Robert Klemme

After playing with each_cons (that seemed promising but I was unable
to put it together) I've noticed good old take.
So I've ended up with this:

# all possible keys
# ex. for 211 keys are [211,11,1,"default"]
def keys
(1..amount_as_array.size).inject(["default"]) { |result,n| result
<< amount_as_array.take(n).join.reverse.to_i }.reverse
end

def amount_as_array
@amount.to_s.split(//).reverse
end

This seems much more idiomatic, not to mention while is almost a code
smell :)

If I understand your requirement properly, all you need is the trailing
number of digits. That could be obtained in a different way:

def keys(i)
if block_given?
i.to_s.length.downto 1 do |n|
yield i % 10**n
end
else
to_enum:)keys, i)
end
end

irb(main):021:0> keys(123) {|x| p x}
123
23
3
=> 3
irb(main):022:0> keys(123).to_a
=> [123, 23, 3]

Kind regards

robert
 
D

drKreso

Great,

Yes I need trailing number of digits. Great idea with %

I've settled for this:

def trailing_digits
(amount_length.downto 1).map { |n| @amount % 10**n } << "default"
end

Thanks,

Best Regards,

Kresimir Bojcic
htttp://www.kresimirbojcic.com


After playing with each_cons (that seemed promising but I was unable
to put it together) I've noticed good old take.
So I've ended up with this:
   # all possible keys
   # ex. for 211 keys are [211,11,1,"default"]
   def keys
     (1..amount_as_array.size).inject(["default"]) { |result,n| result
<<  amount_as_array.take(n).join.reverse.to_i }.reverse
   end
   def amount_as_array
     @amount.to_s.split(//).reverse
   end
This seems much more idiomatic, not to mention while is almost a code
smell :)

If I understand your requirement properly, all you need is the trailing
number of digits.  That could be obtained in a different way:

def keys(i)
   if block_given?
     i.to_s.length.downto 1 do |n|
       yield i % 10**n
     end
   else
     to_enum:)keys, i)
   end
end

irb(main):021:0> keys(123) {|x| p x}
123
23
3
=> 3
irb(main):022:0> keys(123).to_a
=> [123, 23, 3]

Kind regards

        robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top