2017-03-15 7 views
2

私のRails 4.2.6/Ruby 2.2.4アプリケーションでは、文字列を生成するdbクエリメソッドがあります。例えば:gsubに引数として正規表現を書く!方法 - 困惑?

"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris" 

しかし、私が望む結果は次のとおりです。

"Chest, Quads, Hamstrings" 

ドメインが生成された文字列は、異なる組み合わせの多くを持つことができることを意味21匹の筋肉群を、追跡します。しかし、文字列は常に同じパターン、つまり「共通の筋肉名 - 技術的な筋肉名」です。条件ロジックで

、私はこのように、GSUBメソッドに「文字列」引数を渡すことで、私が望む結果を得ることができます。

if @muscle_group_ids == [1, 13, 14] 
    @muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n| n[:name] 
    }.join(', ').gsub!("Chest - pectoralis", "Chest").gsub!("Quads - quadriceps", "Quads").gsub!("Hamstrings - biceps femoris", "Hamstrings") 
end 
=> "Chest, Quads, Hamstrings" 

そのアプローチは実行可能ではありません。退屈で脆い。生成された文字列からダッシュと技術的な名前を削除するには、より良い方法が必要です。私はこれをいかに最高に達成するかについて困惑しています。希望の結果を得るために正規表現を書くことは可能ですか?私がやろうとしていることを達成するために、より簡単で、より良い、よりクリーンなアプローチがありますか?ありがとう!

+0

de、 'MuscleGroup.where(...)をしないでください。map {| n |あなたがこれを行うことができれば、Railsで 'n::name]}'を実行してください。 'MuscleGroup.where(...)。pluck(:name)' –

答えて

2

このようにしますか?

スペースに続いて、彼らは括弧の中にいるので、それは覚えている「言葉」の文字( \w)、( \s+)の任意の数( +)、ハイフン、より多くのスペース、およびないものを探し
irb(main):001:0> s="Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris" 
irb(main):002:0> s.gsub(/(\w+)\s+-\s+[^,]*/, '\1') 
=> "Chest, Quads, Hamstrings" 

コンマ([^,]*)。それはすべての単語を記憶した単語の文字に置き換えます(\1)。

パターンは非常に特殊であり、たとえば共通名が1つの単語。

A lso、私はちょうどgsub上記の結果を返す(と表示、irb)でした。文字列を変更する場合は、gsub!を使用します。

+0

ありがとう。これらはすべて良い答えです。私は他の答えにポイントを与えました。 – codeinspired

+1

@ codeinspired:もしあれば、lassviは受け入れられた答えを得なければなりません。彼はあなたが問題を後ろ向きに扱っていることに気付く最初の人であり、よりクリーンなソリューションを提案しました。 –

2

MuscleGroup番号のCOMMON_NAME

MuscleGroupモデルの内側に新しいメソッドを定義することです最も簡単な方法:

def common_name 
    name.split(' - ').first 
end 

をあなたのコードは次のようになります。

@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |muscle_group| 
    muscle_group.common_name }.join(', ') 

ダブル場合

を分割何らかの理由で、あなたはすでに完全な文字列を持っています。ダブルスプリットは、大きな正規表現よりも堅牢で読みやすくなります。

', 'に分割して"common muscle name - technical muscle name"の配列を取得することができます。その後、' - 'の周りにこれらの文字列のそれぞれを分割し、最初の部分を保つことができます。

"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris". 
    split(', ').map{|s| s.split(' - ').first} 
# ["Chest", "Quads", "Hamstrings"] 

あなたは、配列を持っていたら、あなたが戻って文字列に参加することができます:

"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris". 
    split(', ').map{|s| s.split(' - ').first}.join(', ') 
# "Chest, Quads, Hamstrings" 
5

あなただけ分割することができマップ機能で" -"に名前を付け、これだけのような最初の部分を返す:ASIとして

if @muscle_group_ids == [1, 13, 14] 
    @muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n| 
     n = n[:name].split(" -")[0] 
    }.join(', ') 
end 
=> "Chest, Quads, Hamstrings" 
2
r = /[[:alpha:]]+  # match one or more letters 
     [\s+[:alpha:]+]* # match one or more spaces followed by one or more letters, 
         # zero or more times, to match any words after the first 
     (?=\s+-\s+)  # match a hyphen surrounded by whitespace in a positive lookahead 
    /x    # free-spacing regex definition mode 

"Chest - pectoralis, Quads - quadriceps, Achilles heel - Achilles tendon".scan(r) 
    #=> ["Chest", "Quads", "Achilles heel"] 
+0

共通名に2つの単語がある場合はどうなりますか? –

+0

良い点、@エリック。私は改造をした。 –

関連する問題