2016-06-27 9 views
0

持っている場合:は、ハッシュ値が、私はハッシュを持っているテキスト

universityname = e.university 
topuniversities = CSV.read('lib/assets/topuniversities.csv',{encoding: "UTF-8", headers:true, header_converters: :symbol, converters: :all}) 
hashed_topuniversities = topuniversities.map {|d| d.to_hash} 

hashed_topuniversities.any? {|rank, name| name.split(' ').include?(universityname) }.each do |s| 
    if s[:universityrank] <= 10 
    new_score += 10 
    elsif s[:universityrank] >= 11 && s[:universityrank] <= 25 
    new_score += 5 
    elsif s[:universityrank] >= 26 && s[:universityrank] <= 50 
    new_score += 3 
    elsif s[:universityrank] >= 51 && s[:universityrank] <= 100 
    new_score += 2 
    end 

を基本的にこれが何をしているか、ハッシュを見ていると、ハッシュ値は、大学名が入力されて含まれているかどうかをチェックします。

たとえば、ユーザー入力は「Oxford University」で、ハッシュでは「Oxford」として格納されます。ユーザーはスコアを割り当てることができるようにハッシュに格納されているように入力する必要がありますが、ユーザーが "oxford university"を入力すると、ハッシュ値 "Oxford"を選択して通過する必要があります。

他のすべては正常に動作しますが、.include?は正しく動作しませんが、正確な単語を入力する必要があります。より慣用ルビという点でいくつかのコードの改善に加え

+1

[正規表現](http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm) –

+2

'可算#いずれかをチェックしてください?'ブール値を返します。 'hashed_topuniversities.any? {...} .each'は動作しません。 –

+0

が合意されました。あなたはリンクの部分に一致する正規表現をしたいでしょう。オプションで、ファジーマッチングを使って最良のものと一致するキーを見つけることができますが、それは過剰なもののようです:P – jaydel

答えて

0

あなたのアプローチは(実際には、とにかく)うまくいくとは思えません。 「オックスフォード大学」は簡単な言葉です。「オックスフォード」という言葉の存在を探します。 「カンザス大学」はどうですか?あなたは単に "カンザス"にマッチするように試みますか? "カンザス州立大学"はどうですか?

また、「LSE」、「UCLA」、「USC」、「SUNY」、「LSU」、「RPI」、「Penn」などのよく知られている頭字語または短縮名によって習慣的に参照される大学もあります「State」、「Georgia Tech」、「Berkeley」、および「Cal Tech」である。大学名(例:「カリフォルニア大学ロサンゼルス校」)の句読点や「小さな言葉」についても考える必要があります(例:「at」「the」「」)。

重要なアプリケーションについては、各大学の一般的に使用されるすべての名前のリストを作成し、それらの名前と指定された大学名との完全一致を必要とすると思います(句読点や小さな単語は削除されています) 。さらに合併症(私は対処しないこと)であるいくつかの大学の

hashed_top_universities 
    #=> { "University of California at Berkeley" => 
    #  { rank: 1, names: ["university california", "berkeley", "cal"] }, 
    #  "University of California at Los Angeles" => 
    #  { rank: 2, names: ["ucla"] }, 
    #  "University of Oxford" => 
    #  { rank: 3, names: ["oxford", "oxford university"] } 
    # } 

名の非ASCII文字を含む、:あなたは、おそらくこのように、ハッシュhashed_top_universitiesを変更することでそれを行うことができます。

コード作成の仕組みは次のとおりです。

大学名を指定すると、最初に、大学名をランクにマップするハッシュ(reverse_hash)を作成します。名前はの内部ハッシュのキー:namesの要素の要素と、そのハッシュのキーを構成する完全な大学名と、それらがダウンケースされ、句読点と "小さな単語"が削除された後で構成されます。

PUNCTUATION = ",." 
EXCLUSIONS = %w| of for the at u | 
SCORE = { 1=>10, 3=>7, 25=>5, 50=>3, 100=>2, Float::INFINITY=>0 } 

reverse_hash = hashed_top_universities.each_with_object({}) { |(k,v),h| 
    (v[:names] + [simplify(k)]).each { |name| h[name] = v[:rank] } } 
    #=> {"university california"=>1, "berkeley"=>1, "cal"=>1, 
    #  "university california berkeley"=>1, 
    # "ucla"=>2, "university california los angeles"=>2, 
    # "oxford"=>3, "oxford university"=>3, "university oxford"=>3} 

def simplify(str) 
    str.downcase.delete(PUNCTUATION). 
     gsub(/\b#{Regexp.union(EXCLUSIONS)}\b/,''). 
     squeeze(' ') 
end 

def score(name, reverse_hash) 
    rank = reverse_hash[simplify(name)] 
    SCORE.find { |k,_| rank <= k }.last 
end 

のは、それを試してみましょう。

score("University of California at Berkeley", reverse_hash) 
    #=> 10 
score("Cal", reverse_hash) 
    #=> 10 
score("UCLA", reverse_hash) 
    #=> 7 
score("Oxford", reverse_hash) 
    #=> 7 
1
hashed_topuniversities = topuniversities.map &:to_hash 

univ = hashed_topuniversities.detect do |rank, name| 
    name.downcase.split(' ').include?(universityname.downcase) 
end 

new_score += case univ[:universityrank] 
      when -Float::INFINITY..10 then 10 
      when 11..25 then 5 
      when 26..50 then 3 
      when 50..100 then 2 
      else 0 
      end 

、主変化は、大学名とユーザ入力の両方に呼び出さdowncaseあります。今では大文字と小文字を区別していません。

関連する問題