私はこれらのコード行を書いています:
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つのCharacter
sのString
sを比較したい。単にIgnoreCase
を使用しても機能しません。 '65' ASCII
値を追加しても機能しません。どうすればいいですか?
Character
Java APIのクラス)には、使用できるさまざまな機能があります。
両側で文字を小文字に変換できます:
Character.toLowerCase(name1.charAt(i)) == Character.toLowerCase(name2.charAt(j))
文字が大文字か小文字かを確認するために使用できる方法もあります。
Character.isUpperCase('P')
Character.isLowerCase('P')
実際には、文字列または文字でtoLowerCase
を使用して非常に適切に処理することはできません。問題は、大文字または小文字のいずれかのバリアントグリフがあり、大文字と小文字のどちらを使用するかによって、グリフが保持される場合と保持されない場合があることです。小文字のグリフの2つのバリアントが大文字と小文字を区別せずに比較されると言うとき、の意味は明確ではありません:それらは同じですか? (大文字と小文字が混在するグリフ:\u01c5, \u01c8, \u01cb, \u01f2
またはDž、mixed、Nj、thereもありますが、ここで提案する方法は、完全に大文字または完全に小文字のバリアントと同じ数えられる限り、それらで機能します。)
Char
の使用には追加の問題があります:少なくともJavaのコードポイントによって検出されるように、大文字/小文字のバリアント(それぞれ40)である単一のChar
で表現できない80のコードポイントがあります上部/下部ケーシング。したがって、コードポイントを取得し、これらのケースを変更する必要があります。
しかし、コードポイントはバリアントグリフには役立ちません。
とにかく、バリアントが原因で問題となるグリフの完全なリストを以下に示します。6つのバリアントメソッドに対してどのように対応するかを示しています。
toLowerCase
toUpperCase
toLowerCase
toUpperCase
equalsIgnoreCase
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を正しくする方法がないことです(つまり、点線のバージョンは点線のないバージョンとは異なります)。これらのメソッドはどれも正しい振る舞いを与えず、ロケールを知らない限りできません(つまり、トルコ語以外:i
とI
は大文字小文字を区別せず、トルコ語ではありません)。
全体として、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)
}
このように、使用する前に文字列の大文字と小文字を変更できます
String name1 = fname.getText().toString().toLowerCase();
String name2 = sname.getText().toString().toLowerCase();
その後、残りの操作を続行します。
両方の文字を小文字で入力 して、それらを比較できます。
文字/小文字/大文字を比較するときは、トルコ語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つの文字列の間の位置にある文字を比較する汎用メソッド。
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)
これは、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);
}
トルコ語でも機能すると思いますか?