2016-10-07 7 views
1

私には文字列a5bc2cdf3があります。私はそれをaaaaabcbccdfcdfcdfに広げたいと思います。結果の文字列が連続して2回現れる「BC」の5つの連続「」S、「BC2」の結果が含まれている必要があり、そしてcdf3回繰り返す必要がありますので、文字列で いくつかの条件に基づいてRubyの文字列を拡張するには?

は、a5あります。

入力がa5bc2cdf3で、出力がaaaaabcbccdfcdfcdfの場合、どうすればRubyメソッドで行うことができますか?

def get_character("compressed_string",index) 
    expanded_string = calculate_expanded_string(compressed_string) 
    required_char = expanded_string(char_at, index_number(for eg 3)) 
end 

def calculate_expanded_string(compressed_string) 
    return expanded 
end 
+0

適切な文法を使用するように注意してください。 "私"は "私"です。 Stack Overflowはディスカッション・リストではなくオンラインの参考書であり、文法、スペル、句読点および書式設定の問題です。 –

答えて

3

あなたは1+文字(([a-zA-Z]+))と1+数字で((\d+)を)Ruby online demo

/([a-zA-Z]+)(\d+)/一致するstubstringsを参照してください

.gsub(/([a-zA-Z]+)(\d+)/){$1*$2.to_i} 

のような正規表現を使用することができ、それらをキャプチャします2つのグループに分けられ、後にブロック内で必要な文字列を返すために使用されます。

[a-zA-Z]の代わりに、任意の文字に一致する\p{L}を使用することを検討してください。

オリジナルの「圧縮」文字列で指定されたインデックスに達すると、gsubから抜け出します。それはまだ可能である、this Ruby demoを参照してください。

s = 'a5bc2cdf3'    # input string 
index = 5      # break index 
result = ""     # expanded string 
s.gsub!(/([a-zA-Z]+)(\d+)/){ # regex replacement 
    result << $1*$2.to_i  # add to the resulting string 
    break if Regexp.last_match.end(0) >= index # Break if the current match end index is bigger or equal to index 
} 
puts result[index]   # Show the result 
# => b 

簡潔にするために、あなたは$~Regexp.last_matchを置き換えることができます。

+0

しかし、ここでは、どの位置に番号があるのか​​を知っています。文字列が動的にこのメソッドに来る場合、いくつの番号が存在し、どの位置に番号があるのか​​わかりません。 – John

+0

ちょうど明確にする:あなたは拡大の数を制限できるようにしたいですか? 'インデックス 'は何をすべきか?展開文字列 "aaaaabcbccdfcdfcdf"に –

+0

を追加します(インデックスを渡します)。それが "5"であれば、インデックスがゼロから始まるので、 "b"チャーチャーを取得する必要があります。 – John

2

単純なRegExを使って圧縮された文字列を移動するには、scanを使用することをお勧めします。現在の(合計)の長さを知る

def get_character(compressed_string, index) 
    result = nil 

    compressed_string.scan(/([^\d]+)(\d+)/).inject(0) do |total_length, (chars, count)| 
    decoded_string = chars * count.to_i 
    total_length += decoded_string.length 

    if index < total_length 
     result = decoded_string[-(total_length - index)] 
     break 
    else 
     total_length 
    end 
    end 

    result 
end 

電流拡張文字列が要求されたインデックスを含む場合、一つのループから抜け出すことができます。文字列は完全にはデコードされません。

このコードは次のような結果

get_character("a5bc2cdf3", 5) # => "b" 
get_character("a5bc2cdf3", 10) # => "d" 
get_character("a5bc2cdf3", 20) # => nil 
+0

ちょうどこのスニペットがWiktorsの答えに対するコメントのためにこのように動作することを追加したかっただけです。索引に達すると、コードは入力の解凍を停止する必要があります。 –

0

にちょうど別の方法を提供します。私はウィクトールの方法を長い間好む。

私が使用したい
def stringy str, index 
    lets, nums = str.split(/\d+/), str.split(/[a-z]+/)[1..-1].map(&:to_i) 
    ostr = lets.zip(nums).map { |l,n| l*n }.join 
    ostr[index] 
end 

str = 'a5bc2cdf3' 
p stringy str, 5 #=> "b" 
0

str = "a5bc2cdf3" 
str.split(/(\d+)/).each_slice(2).map { |s, c| s * c.to_i }.join # => "aaaaabcbccdfcdfcdf" 

は、ここでそれが壊れる方法は次のとおりです。

str.split(/(\d+)/) # => ["a", "5", "bc", "2", "cdf", "3"] 

それが正規表現グループにいた場合splitは上の分割されている値を返しますので、これは動作します: /(\d+)/

str.split(/(\d+)/).each_slice(2).to_a # => [["a", "5"], ["bc", "2"], ["cdf", "3"]] 

得られた配列はeach_slice(2)を用いて繰り返し、その関連カウントする列に分けることができます。

str.split(/(\d+)/).each_slice(2).map { |s, c| s * c.to_i } # => ["aaaaa", "bcbc", "cdfcdfcdf"] 

配列のその配列は、文字を繰り返す文字列の*を使用していますmapで処理することができます。

最後にjoinは、結果として得られるすべての拡張文字列を連結して1つの文字列に戻します。

関連する問題