79

フィールドを持つActiveRecordモデルFooがありnameます。ユーザーが名前で検索できるようにしたいのですが、検索では大文字と小文字やアクセントを無視して検索したいと考えています。canonical_nameしたがって、検索対象のフィールドも保存しています。

class Foo
  validates_presence_of :name

  before_validate :set_canonical_name

  private

  def set_canonical_name
    self.canonical_name ||= canonicalize(self.name) if self.name
  end

  def canonicalize(x)
    x.downcase.  # something here
  end
end

アクセント付きの文字を置き換えるには、「ここに何か」を入力する必要があります。より良いものはありますか

x.downcase.gsub(/[àáâãäå]/,'a').gsub(/æ/,'ae').gsub(/ç/, 'c').gsub(/[èéêë]/,'e')....

さらに言えば、私は Ruby 1.9 を使用していないため、これらの Unicode リテラルを自分のコードに入れることはできません。実際の正規表現はもっと醜く見えます。

4

16 に答える 16

99

ActiveSupport::Inflector.transliterate(Rails 2.2.1+ および Ruby 1.9 または 1.8.7 が必要)

例:

>> ActiveSupport::Inflector.transliterate("àáâãäå").to_s => "aaaaaa"

于 2011-08-23T11:47:19.760 に答える
63

Rails には正規化用のビルトインが既にあります。これを使用して文字列を正規化して KD を形成し、次のように他の文字 (つまりアクセント記号) を削除するだけです。

>> "àáâãäå".mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.to_s
=> "aaaaaa"
于 2008-11-15T14:18:52.243 に答える
20

私はこのアプローチをたくさん試しましたが、これらの要件の 1 つまたはいくつかを達成していませんでした。

  • スペースを尊重する
  • 'ñ' 文字を尊重する
  • 大文字と小文字の区別 (元の質問の要件ではないことはわかっていますが、文字列をlowcaseに移動することは難しくありません)

これでした:

# coding: utf-8
string.tr(
  "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
  "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
)

http://blog.slashpoundbang.com/post/12938588984/remove-all-accents-and-diacritics-from-string-in-ruby

「ñ」文字を尊重するために文字リストを少し変更する必要がありますが、簡単な作業です。

于 2012-09-10T14:43:03.430 に答える
12

私の答え: String#parameterizeメソッド:

"Le cœur de la crémiére".parameterize
=> "le-coeur-de-la-cremiere"

Rails 以外のプログラムの場合:

アクティブサポートをインストール:gem install activesupport次に:

require 'active_support/inflector'

"a&]'s--3\014\xC2àáâã3D".parameterize
# => "a-s-3-3d"
于 2013-07-23T12:07:55.117 に答える
7

文字列を分解し、文字列から非スペーシング マークを削除します。

irb -ractive_support/all
> "àáâãäå".mb_chars.normalize(:kd).gsub(/\p{Mn}/, '')
aaaaaa

.rb ファイルで使用する場合、これも必要になる場合があります。

# coding: utf-8

ここのnormalize(:kd)部分は、可能な場合は分音記号を分割し (例: "n with tilda" という単一文字は、n の後に分音記号付きのチルダ文字を組み合わせた文字に分割されます)、gsubその後、すべての分音記号を削除します。

于 2012-01-15T15:37:14.523 に答える
7

私はあなたがその道を何をすべきか本当に分かっていないのではないかと思います。この種の文字を使用する市場向けに開発している場合、ユーザーはおそらくあなたが一種の ... pipであると考えるでしょう。ユーザーにとって、「å」は「a」に近い意味でさえないからです。別の道をたどって、ASCII 以外の方法での検索について読んでください。これは、誰かが unicode と collat​​ion を発明したケースの 1 つにすぎませ

非常に遅い PS :

http://www.w3.org/International/wiki/Case_folding http://www.w3.org/TR/charmod-norm/#sec-WhyNormalization

それに加えて、照合へのリンクがmsdnページに移動する方法がわかりませんが、そこに残します。http://www.unicode.org/reports/tr10/だったはずです

于 2008-10-23T07:41:08.327 に答える
3

テキストを正規化フォーム D に変換し、Unicode カテゴリの非スペーシング マーク (Mn) を持つすべてのコードポイントを削除して、正規化フォーム C に戻します。

詳細については、http ://www.siao2.com/2005/02/19/376617.aspxおよびhttp://www.siao2.com/2007/05/14/2629747.aspxを参照してください。

于 2008-10-22T14:52:42.077 に答える
2

おそらく、Unicode 分解 (「NFD」) が必要です。文字列を分解した後、[A-Za-z] 以外のものを除外します。æ は "ae" に分解され、ã は "a~" に分解されます (おおよそ - 発音区別記号は別の文字になります)。そのため、フィルタリングは合理的な近似値を残します。

于 2008-10-22T12:14:25.513 に答える
1

iconv:

http://groups.google.com/group/ruby-talk-google/browse_frm/thread/8064dcac15d688ce

=============

私が理解できないperlモジュール:

http://www.ahinea.com/en/tech/accented-translate.html

============

ブルートフォース(多くのhtose生き物がいます!:

http://projects.jkraemer.net/acts_as_ferret/wiki#UTF-8support

http://snippets.dzone.com/posts/show/2384

于 2008-10-22T12:50:21.417 に答える
1

これを読んで非ASCII文字をすべて削除したい人にとって、これは役立つかもしれません。最初の例をうまく使用しました。

于 2010-08-29T12:48:51.453 に答える
0

foo.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.to_s ソリューションを機能させるのに問題がありました。私は Rails を使用しておらず、私のアクティブ サポート/Ruby バージョンと競合があり、その原因を突き止めることができませんでした。

ruby-unf gem を使用するのが良い代替手段のようです:

require 'unf'
foo.to_nfd.gsub(/[^\x00-\x7F]/n,'').downcase

私が知る限り、これは .mb_chars.normalize(:kd) と同じことを行います。これは正しいです?ありがとう!

于 2012-09-19T11:04:07.273 に答える
-3

笑..私はこれを試しました..そしてそれは機能しています..私はまだ理由がよくわかりません..しかし、私がこの4行のコードを使用すると:

  • str = str.gsub(/[^a-zA-Z0-9 ]/,"")
  • str = str.gsub(/[ ]+/," ")
  • str = str.gsub(/ /,"-")
  • str = str.downcase

それはファイル名からアクセントを自動的に削除します..私が削除しようとしていた(ファイル名からのアクセントと名前の変更よりも)それが役に立ったことを願っています:)

于 2009-03-29T08:02:25.407 に答える