1

そこで、「the」、「and」、「if」などのあいまいな単語を除いて、文字列内のすべての単語の最初の文字を大文字にするメソッド「#titleize」を定義しようとしています。

これまでの私のコード:

def titleize(string)
words = []
stopwords = %w{the a by on for of are with just but and to the my had some in} 

string.scan(/\w+/) do |word|
    if !stopwords.include?(word) 
        words << word.capitalize
    else 
        words << word 
    end

words.join(' ')
end

問題は if/else セクションにあります。文字列に対してメソッドを実行すると、「構文エラー、予期しない $end、keyword_end が必要です」というメッセージが表示されます。

通常 {中かっこ} 内のコード ブロックに入る、if/else の簡略版を使用した場合、コードは機能すると思います。この略記の構文は、次のようなものです。

string.scan(/\w+/) { |word| !stopwords.include?(word) words << word.capitalize : words       
    <<  word }

...と

words << word.capitalize 

!stopwords.include?(word) が true を返す場合に発生し、

words << word

!stopwords.include?(単語) が false を返す場合に発生します。しかし、これもうまくいきません!

次のように見える場合もあります (これは少し異なる/より効率的なアプローチです - 個別の配列がインスタンス化されていません):

string.scan(/\w+/) do |word|
    !stopwords.include?(word) word.capitalize : word
end.join(' ')

(メソッド内でのメソッドの呼び出しから Ruby の Titleize まで) ...しかし、このコードを実行しても「構文エラー」メッセージが表示されます。

そう!私が言及している構文を知っている人はいますか?覚えるのを手伝ってくれませんか?または、このコードが機能しない別の理由を指摘できますか?

4

4 に答える 4

3

私はあなたが欠けていると思いますend

string.scan(/\w+/) do |word|
    if !stopwords.include?(word) 
        words << word.capitalize
    else 
        words << word 
    end
end #<<<<add this

簡略版の場合は、次のようにします。

string.scan(/\w+/).map{|w| stopwords.include?(w) ? w : w.capitalize}.join(' ')
于 2013-10-21T23:11:23.390 に答える
1

Active Support にはtitleize、文字列内の単語を大文字にするため、出発点として役立つメソッドがありますが、完全にインテリジェントというわけではありません。それはストップワードに無駄を置きます。ただし、それらを復元するための後処理を少し行うと、これがうまく修正されます。

これが私がそれを行う方法です:

require 'active_support/core_ext/string/inflections'

STOPWORDS = Hash[
  %w{the a by on for of are with just but and to the my had some in}.map{ |w| 
    [w.capitalize, w]
  }
]


def my_titlize(str)
  str.titleize.gsub(
    /(?!^)\b(?:#{ STOPWORDS.keys.join('|') })\b/,
    STOPWORDS
  )
end
# => /(?!^)\b(?:The|A|By|On|For|Of|Are|With|Just|But|And|To|My|Had|Some|In)\b/

my_titlize('Jackdaws love my giant sphinx of quartz.')
# => "Jackdaws Love my Giant Sphinx of Quartz."

my_titlize('the rain in spain stays mainly in the plain.')
# => "The Rain in Spain Stays Mainly in the Plain."

my_titlize('Negative lookahead is indispensable')
# => "Negative Lookahead Is Indispensable"

私がこれを行う理由は、YAML ファイルまたはデータベース テーブルを作成して、ストップワードのリストを提供するのが非常に簡単だからです。その単語の配列からハッシュと正規表現を簡単に作成できます。正規表現は に供給されgsub、正規表現エンジンを使用してストップワードを修正します。

作成されるハッシュは次のとおりです。

{
  "The"=>"the",
  "A"=>"a",
  "By"=>"by",
  "On"=>"on",
  "For"=>"for",
  "Of"=>"of",
  "Are"=>"are",
  "With"=>"with",
  "Just"=>"just",
  "But"=>"but",
  "And"=>"and",
  "To"=>"to",
  "My"=>"my",
  "Had"=>"had",
  "Some"=>"some",
  "In"=>"in"
}

作成される正規表現は次のとおりです。

/(?!^)\b(?:The|A|By|On|For|Of|Are|With|Just|But|And|To|My|Had|Some|In)\b/

正規表現パターンの単語にヒットするgsubと、ハッシュでルックアップを行い、値を文字列に代入します。

このコードdowncaseでは、大文字の単語を逆にする、またはその他の計算された方法を使用できますが、オーバーヘッドが追加されます。gsub、および正規表現エンジンは非常に高速です。その理由の 1 つは、ハッシュと正規表現がストップワード リストのループを回避するためです。そのため、コードを大幅に遅くすることなくリストが巨大になる可能性があります。もちろん、エンジンは Ruby のさまざまなバージョンで変更されているため、古いバージョンではうまく機能しないため、Ruby < 2.0 のベンチマークを実行してください。

于 2013-10-22T03:07:40.733 に答える
0

最適化されていないコードでバグを探すのは困難です。標準的な方法でそれを行い、起こりうるエラーを見つけやすくします。

class String
  SQUELCH_WORDS = %w{the a by on for of are with just but and to the my had some in}

  def titleize
    gsub /\w+/ do |s|
      SQUELCH_WORDS.include?( s ) ? s : s.capitalize
    end
  end
end

"20,000 miles under the sea".titleize #=> "20,000 Miles Under the Sea"
于 2013-10-21T23:18:52.873 に答える
0

end(メソッドを閉じるための)がないだけでなく、ブロックwords.join(' ')内にあります。これはscan` を意味します。scanwords is joining every time you iterate through

私はあなたがこれを望んでいると思います:

def titleize(string)
  words = []
  stopwords = %w{the a by on for of are with just but and to the my had some in} 

  string.scan(/\w+/) do |word|
      if !stopwords.include?(word) 
          words << word.capitalize
      else 
          words << word 
      end
  end

  words.join(' ')
end

コードはクリーンアップできますが、この時点で基本的なフローは適切です。

于 2013-10-22T15:21:35.280 に答える