web-dev-qa-db-ja.com

プリミティブ型の大文字小文字を無視した文字の比較方法

私はこれらのコード行を書いています:

String name1 = fname.getText().toString();
String name2 = sname.getText().toString();
aru = 0;

count1 = name1.length();
count2 = name2.length();
for (i = 0; i < count1; i++)
{  
    for (j = 0; j < count2; j++)
    { 
        if (name1.charAt(i)==name2.charAt(j))
            aru++;
    }
    if(aru!=0)
        aru++;
}

大文字小文字を無視して、2つのCharactersのStringsを比較したい。単にIgnoreCaseを使用しても機能しません。 '65' ASCII値を追加しても機能しません。どうすればいいですか?

21
Arush Kamboj

Character Java APIのクラス)には、使用できるさまざまな機能があります。

両側で文字を小文字に変換できます:

Character.toLowerCase(name1.charAt(i)) == Character.toLowerCase(name2.charAt(j))

文字が大文字か小文字かを確認するために使用できる方法もあります。

Character.isUpperCase('P')
Character.isLowerCase('P') 
38
Shehzad

実際には、文字列または文字でtoLowerCaseを使用して非常に適切に処理することはできません。問題は、大文字または小文字のいずれかのバリアントグリフがあり、大文字と小文字のどちらを使用するかによって、グリフが保持される場合と保持されない場合があることです。小文字のグリフの2つのバリアントが大文字と小文字を区別せずに比較されると言うとき、の意味は明確ではありません:それらは同じですか? (大文字と小文字が混在するグリフ:\u01c5, \u01c8, \u01cb, \u01f2またはDž、mixed、Nj、thereもありますが、ここで提案する方法は、完全に大文字または完全に小文字のバリアントと同じ数えられる限り、それらで機能します。)

Charの使用には追加の問題があります:少なくともJavaのコードポイントによって検出されるように、大文字/小文字のバリアント(それぞれ40)である単一のCharで表現できない80のコードポイントがあります上部/下部ケーシング。したがって、コードポイントを取得し、これらのケースを変更する必要があります。

しかし、コードポイントはバリアントグリフには役立ちません。

とにかく、バリアントが原因で問題となるグリフの完全なリストを以下に示します。6つのバリアントメソッドに対してどのように対応するかを示しています。

  1. キャラクターtoLowerCase
  2. キャラクターtoUpperCase
  3. 文字列toLowerCase
  4. 文字列toUpperCase
  5. 文字列equalsIgnoreCase
  6. 文字toLowerCase(toUpperCase)(またはその逆)

これらのメソッドでは、Sはバリアントが互いに同じように扱われることを意味し、Dはバリアントが互いに異なるものとして扱われることを意味します。

Behavior     Unicode                             Glyphs
===========  ==================================  =========
1 2 3 4 5 6  Upper  Lower  Var Up Var Lo Vr Lo2  U L u l l2
- - - - - -  ------ ------ ------ ------ ------  - - - - -
D D D D S S  \u0049 \u0069 \u0130 \u0131         I i İ ı   
S D S D S S  \u004b \u006b \u212a                K k K     
D S D S S S  \u0053 \u0073        \u017f         S s   ſ   
D S D S S S  \u039c \u03bc        \u00b5         Μ μ   µ   
S D S D S S  \u00c5 \u00e5 \u212b                Å å Å     
D S D S S S  \u0399 \u03b9        \u0345 \u1fbe  Ι ι   ͅ ι 
D S D S S S  \u0392 \u03b2        \u03d0         Β β   ϐ   
D S D S S S  \u0395 \u03b5        \u03f5         Ε ε   ϵ   
D D D D S S  \u0398 \u03b8 \u03f4 \u03d1         Θ θ ϴ ϑ   
D S D S S S  \u039a \u03ba        \u03f0         Κ κ   ϰ   
D S D S S S  \u03a0 \u03c0        \u03d6         Π π   ϖ   
D S D S S S  \u03a1 \u03c1        \u03f1         Ρ ρ   ϱ   
D S D S S S  \u03a3 \u03c3        \u03c2         Σ σ   ς   
D S D S S S  \u03a6 \u03c6        \u03d5         Φ φ   ϕ   
S D S D S S  \u03a9 \u03c9 \u2126                Ω ω Ω     
D S D S S S  \u1e60 \u1e61        \u1e9b         Ṡ ṡ   ẛ   

これをさらに複雑にしているのは、トルコ語を知っている場合を除き、トルコ語Iを正しくする方法がないことです(つまり、点線のバージョンは点線のないバージョンとは異なります)。これらのメソッドはどれも正しい振る舞いを与えず、ロケールを知らない限りできません(つまり、トルコ語以外:iIは大文字小文字を区別せず、トルコ語ではありません)。

全体として、toUpperCaseを使用すると、大文字のバリアントが5つ(トルコ語をカウントしない場合は4つ)しかないため、最も近い近似が得られます。

また、これら5つの面倒なケースを具体的にインターセプトし、それらの単独でtoUpperCase(toLowerCase(c))を呼び出すこともできます。ガードを慎重に選択する場合(c < 0x130 || c > 0x212Bの場合はtoUpperCaseだけで、他の選択肢を介して作業する場合)、低範囲の文字に対して〜20%の速度ペナルティしか得られません(単一の文字を変換する場合は〜4xと比較して)ストリングとequalsIgnoreCaseそれらに)、危険ゾーンにたくさんいる場合は約2倍のペナルティのみ。まだ点線Iでロケールの問題がありますが、それ以外はまともな形です。もちろん、より大きな文字列でequalsIgnoreCaseを使用できる場合は、それを行うことをお勧めします。

サンプルScalaジョブを実行するコード:

def elevateCase(c: Char): Char = {
  if (c < 0x130 || c > 0x212B) Character.toUpperCase(c)
  else if (c == 0x130 || c == 0x3F4 || c == 0x2126 || c >= 0x212A)
    Character.toUpperCase(Character.toLowerCase(c))
  else Character.toUpperCase(c)
}
13
Rex Kerr

このように、使用する前に文字列の大文字と小文字を変更できます

String name1 = fname.getText().toString().toLowerCase(); 
String name2 = sname.getText().toString().toLowerCase();

その後、残りの操作を続行します。

8
Azhar Shaikh

両方の文字を小文字で入力 して、それらを比較できます。

4
assylias

文字/小文字/大文字を比較するときは、トルコ語Iの問題を考慮する必要があります。

Stringに変換し、不変カルチャでtoLowerCaseを使用することをお勧めします(少なくともほとんどの場合)。

public final static Locale InvariantLocale = new Locale(Empty、Empty、Empty); str.toLowerCase(InvariantLocale)

同様のC#を参照してください string.ToLower()およびstring.ToLowerInvariant()

注:String.equalsIgnoreCaseを使用しないでください http://nikolajlindberg.blogspot.co.il/2008/03/beware-of-Java-comparing-turkish.html

2
Dekel

大文字と小文字を区別せずに2つの文字列の間の位置にある文字を比較する汎用メソッド。

public static boolean isEqualIngoreCase(char one, char two){
    return Character.toLowerCase(one)==Character .toLowerCase(two);
}

public static boolean isEqualStringCharIgnoreCase(String one, String two, int position){
    char oneChar = one.charAt(position);
    char twoChar = two.charAt(position);
    return isEqualIngoreCase(oneChar, twoChar);
}

関数呼び出し

boolean isFirstCharEqual = isEqualStringCharIgnoreCase("abc", "ABC", 0)
0
Siddarth Kanted

これは、JDKが行う方法です(OpenJDK 8から適応 String.Java/regionMatches ):

static boolean charactersEqualIgnoringCase(char c1, char c2) {
  if (c1 == c2) return true;

  // If characters don't match but case may be ignored,
  // try converting both characters to uppercase.
  char u1 = Character.toUpperCase(c1);
  char u2 = Character.toUpperCase(c2);
  if (u1 == u2) return true;

  // Unfortunately, conversion to uppercase does not work properly
  // for the Georgian alphabet, which has strange rules about case
  // conversion.  So we need to make one last check before
  // exiting.
  return Character.toLowerCase(u1) == Character.toLowerCase(u2);
}

トルコ語でも機能すると思いますか?

0
Stefan Reich