2010-12-22 9 views
6
例えば

、言葉「スタック」、私はのような配列を取得したい:私はそのようなコードでこれをしなかったRubyで文字列を分割してすべての部分文字列を取得する最も良い方法は何ですか?

['s', 'st', 'sta', ... 'stack', 't', 'ta', ... , 'c', 'ck', 'k'] 

def split_word(str) 
    result = [] 
    chas = str.split("") 
    len = chas.size 
    (0..len-1).each do |i| 
    (i..len-1).each do |j| 
     result.push(chas[i..j].join) 
    end 
    end 
    result.uniq 
end 

がそれを行うには良いとクリーンな方法は何ですか?ありがとう。

+0

重複があってもなくてもかまいませんか? –

+0

重複なし、ありがとう! –

+0

一般的なアドバイス:「init empty + iterate + push + return」のパターンに従う代わりにmap(functional)を使うのが便利です。 – tokland

答えて

11
def split_word s 
    (0..s.length).inject([]){|ai,i| 
    (1..s.length - i).inject(ai){|aj,j| 
     aj << s[i,j] 
    } 
    }.uniq 
end 

そして、あなたはまた、代わりに結果のための配列のSetの使用を検討することができます。

PS:それはmap(機能)を使用することは通常より明確にし、よりコンパクトだ

def split_word(s) 
    0.upto(s.length - 1).flat_map do |start| 
    1.upto(s.length - start).map do |length| 
     s[start, length] 
    end 
    end.uniq 
end 

groups = split_word("stack") 
# ["s", "st", "sta", "stac", "stack", "t", "ta", "tac", "tack", "a", "ac", "ack", "c", "ck", "k"] 

代わりに:私は書きたい

def split_word s 
    indices = (0...s.length).to_a 
    indices.product(indices).reject{|i,j| i > j}.map{|i,j| s[i..j]}.uniq 
end 
+0

どのようなクールな解決策! –

+0

ユーザーからの提案の後に2番目の解決策がある@steel –

2

そう思わないでください。

は、ここに私が試みたバージョンです:

def split_word(str) 
    length = str.length - 1 
    [].tap do |result| 
    0.upto(length) do |i| 
     length.downto(i) do |j| 
     substring = str[i..j] 
     result << substring unless result.include?(substring) 
     end 
    end 
    end 
end 
+0

良い!それは動作し、よりきれいに見えます。 –

3

:ここでは、アレイの製品に基づいて、別のアイデアは、ですパターン初期化空白+各+追加+返信(必須)。

+0

はい、あなたは正しいtoklandです。私は命令的なパターンよりも機能的なパターンも好む。あなたの提案をありがとう!そしてどのパターンがより良いパフォーマンスを持っていると思いますか? –

+0

@ pake007:まあ、通常は速いと言いましたが、ここではRubyの配列の平坦さと非怠惰のために私はうんざりしています。とにかく、パフォーマンスのために汗を流さないでください、違いはおそらく最小です。 – tokland

0

後で、これは私があなたのコードを少し再フォーマットして得たものです。

def substrings(string) 
    siz = string.length 
    answer = [] 

    (0..siz-1).each do |n| 
    (n..siz-1).each do |i| 
     answer << string[n..i] 
    end 
    end 
    answer 
end 
2
def substrings(str) 
    output = [] 
    (0...str.length).each do |i| 
    (i...str.length).each do |j| 
     output << str[i..j] 
    end 
    end 
    output 
end 

これはあなたの方法のほんのクリーンアップバージョンであり、それは私には少し明確に読み込み、それを行うには

2
def substrings(str) 
    (0...str.length).map do |i| 
    (i...str.length).each { |j| str[i..j]} 
    end 
end 

ちょうど別の方法で、)=以下の手順で動作します。

関連する問題