2015-03-09 3 views
2

Есть ли лучший способ нарезать слово в рубине? Мое решение:slice word with previous character

str="TAMILNADU" 
pairs=[] 
numPairs= str.length-1 
i=0 
while i<numPairs do 
    pairs[i] = str.slice(i,2) 
    i+=1 
end 

Результат

["TA", "AM", "MI", "IL", "LN", "NA", "AD", "DU"] 
+0

Другой способ: 'str [0 ..- 2] .chars.zip (str [1 ..- 1] .chars) .map (&: join)'. Если порядок элементов результата не важен, это также работает: 'str.scan (/../). Concat (str [1 ..- 1] .scan (/../))'. –

ответ

1

Другой вариант:

str = "TAMILNADU" 

(0...str.size-1).map{|x| str[x,2]} 
# => ["TA", "AM", "MI", "IL", "LN", "NA", "AD", "DU"] 
+0

Я дал тот же ответ, что и вы .. :) Не последовал .. hehehe –

4

И еще один, используя положительный предпросмотр:

str = 'TAMILNADU' 
str.scan(/(.)(?=(.))/).map(&:join) 
#=> ["TA", "AM", "MI", "IL", "LN", "NA", "AD", "DU"] 
1

Спасибо (@ Дверная ручка, @ hirolau, @ Стефан @ Cary Swoveland) для всех ваших ответов найти контрольный отчет ниже.

Обновлено (Вт - Mar- 2015)

require 'benchmark/ips' 
    Benchmark.ips do |x| 
     str = "TAMILNADU" 
     x.report("1") { 
     pairs=[] 
     numPairs= str.length()-1 
     i=0 
     while i<numPairs do 
      pairs[i] = str.slice(i,2) 
      i+=1 
     end 
     } 
     x.report("2") { 
     str.chars.each_cons(2).map(&:join) 
     } 
     x.report("3") { 
     (0...str.size-1).map{|x| str[x,2]} 
     } 
     x.report("4"){ 
     str.scan(/(.)(?=(.))/).map(&:join) 
     } 
     x.report("5"){ 
     str.gsub(/(.)/,'\1\1')[1...-1].scan(/../) 
     } 
     x.report("6"){ 
     str.gsub(/./) { |c| c*2 }[1...-1].scan(/../) 
     } 
     x.compare! 
    end 
Calculating ------------------------------------- 
        1 37.355k i/100ms 
        2  9.703k i/100ms 
        3 26.961k i/100ms 
        4  7.950k i/100ms 
        5  6.302k i/100ms 
        6  7.804k i/100ms 
------------------------------------------------- 
        1 508.411k (±11.1%) i/s -  2.503M 
        2 107.568k (± 5.1%) i/s - 543.368k 
        3 332.923k (±10.2%) i/s -  1.672M 
        4  88.410k (± 4.5%) i/s - 445.200k 
        5  67.694k (± 4.8%) i/s - 340.308k 
        6  85.000k (± 5.8%) i/s - 429.220k 

Comparison: 
        1: 508410.6 i/s 
        3: 332923.4 i/s - 1.53x slower 
        2: 107567.7 i/s - 4.73x slower 
        4: 88409.9 i/s - 5.75x slower 
        6: 85000.2 i/s - 5.98x slower 
        5: 67694.2 i/s - 7.51x slower 
0

Другой способ с использованием регулярных выражений:

str.gsub(/(.)/,'\1\1')[1...-1].scan(/../) 
    #=> ["TA", "AM", "MI", "IL", "LN", "NA", "AD", "DU"] 

или вариант:

str.gsub(/./) { |c| c*2 }[1...-1].scan(/../) 

Любой другой:

a = [] 
e = str.each_char 
loop do 
    a << (e.next << e.peek) 
end 
a 

Редактировать: я добавил последний метод после того, как был проведен бенчмаркинг, поэтому я сам выполнил тест. Это было мертво. (Мне все равно нравится.)