web-dev-qa-db-ja.com

indexOf大文字と小文字を区別しますか?

IndexOf(String)メソッドは大文字と小文字を区別しますか?ある場合、大文字と小文字を区別しないバージョンがありますか?

66
Brian

indexOf()メソッドはすべて大文字と小文字を区別します。事前に文字列を大文字/小文字に変換することで、大文字と小文字を区別しない(大まかに、壊れた方法で、多くのケースで機能する)ことができます。

s1 = s1.toLowerCase(Locale.US);
s2 = s2.toLowerCase(Locale.US);
s1.indexOf(s2);
63
Joey

IndexOf(String)メソッドは大文字と小文字を区別しますか?

はい、大文字と小文字が区別されます。

@Test
public void indexOfIsCaseSensitive() {
    assertTrue("Hello World!".indexOf("Hello") != -1);
    assertTrue("Hello World!".indexOf("hello") == -1);
}

ある場合、大文字と小文字を区別しないバージョンがありますか?

いいえ、ありません。 indexOfを呼び出す前に、両方の文字列を小文字に変換できます。

@Test
public void caseInsensitiveIndexOf() {
    assertTrue("Hello World!".toLowerCase().indexOf("Hello".toLowerCase()) != -1);
    assertTrue("Hello World!".toLowerCase().indexOf("hello".toLowerCase()) != -1);
}
39
dfa

Apache Commons LangライブラリのStringUtilsクラスに大文字と小文字を区別しないメソッドがあります

indexOfIgnoreCase(CharSequence str、CharSequence searchStr)

18
deepika

はい、indexOfでは大文字と小文字が区別されます。

私が見つけた大文字小文字を区別しない最良の方法は次のとおりです。

_String original;
int idx = original.toLowerCase().indexOf(someStr.toLowerCase());
_

大文字と小文字を区別しないindexOf()を実行します。

16
jjnguy

ヒープメモリを割り当てない私のソリューションを次に示します。したがって、ここで説明した他のほとんどの実装よりも大幅に高速になります。

public static int indexOfIgnoreCase(final String haystack,
                                    final String needle) {
    if (needle.isEmpty() || haystack.isEmpty()) {
        // Fallback to legacy behavior.
        return haystack.indexOf(needle);
    }

    for (int i = 0; i < haystack.length(); ++i) {
        // Early out, if possible.
        if (i + needle.length() > haystack.length()) {
            return -1;
        }

        // Attempt to match substring starting at position i of haystack.
        int j = 0;
        int ii = i;
        while (ii < haystack.length() && j < needle.length()) {
            char c = Character.toLowerCase(haystack.charAt(ii));
            char c2 = Character.toLowerCase(needle.charAt(j));
            if (c != c2) {
                break;
            }
            j++;
            ii++;
        }
        // Walked all the way to the end of the needle, return the start
        // position that this was found.
        if (j == needle.length()) {
            return i;
        }
    }

    return -1;
}

そして、正しい動作を検証する単体テストを次に示します。

@Test
public void testIndexOfIgnoreCase() {
    assertThat(StringUtils.indexOfIgnoreCase("A", "A"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("a", "A"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("A", "a"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("a", "a"), is(0));

    assertThat(StringUtils.indexOfIgnoreCase("a", "ba"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("ba", "a"), is(1));

    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", " Royal Blue"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase(" Royal Blue", "Royal Blue"), is(1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "royal"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "oyal"), is(1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "al"), is(3));
    assertThat(StringUtils.indexOfIgnoreCase("", "royal"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", ""), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "BLUE"), is(6));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "BIGLONGSTRING"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "Royal Blue LONGSTRING"), is(-1));  
}
11
Zach Vorhies

はい、大文字と小文字が区別されます。大文字と小文字を区別しないindexOfを行うには、検索する前にStringとStringパラメーターの両方を大文字に変換します。

String str = "Hello world";
String search = "hello";
str.toUpperCase().indexOf(search.toUpperCase());

ToUpperCaseは、状況によっては機能しない場合があることに注意してください。たとえば、これ:

String str = "Feldbergstraße 23, Mainz";
String find = "mainz";
int idxU = str.toUpperCase().indexOf (find.toUpperCase ());
int idxL = str.toLowerCase().indexOf (find.toLowerCase ());

idxUは20になりますが、これは間違っています! idxLは19で、これは正しいです。問題の原因は、toUpperCase()が「ß」文字を2つの文字「SS」に変換し、これによりインデックスがオフになることです。

したがって、常にtoLowerCase()に固執する

10
Nick Lewis

返されたインデックス値で何をしていますか?

それを使用して文字列を操作している場合、代わりに正規表現を使用できませんか?

import static org.junit.Assert.assertEquals;    
import org.junit.Test;

public class StringIndexOfRegexpTest {

    @Test
    public void testNastyIndexOfBasedReplace() {
        final String source = "Hello World";
        final int index = source.toLowerCase().indexOf("hello".toLowerCase());
        final String target = "Hi".concat(source.substring(index
                + "hello".length(), source.length()));
        assertEquals("Hi World", target);
    }

    @Test
    public void testSimpleRegexpBasedReplace() {
        final String source = "Hello World";
        final String target = source.replaceFirst("(?i)hello", "Hi");
        assertEquals("Hi World", target);
    }
}
3
toolkit

同じ問題がありました。正規表現とApache StringUtils.indexOfIgnoreCase-Methodを試しましたが、どちらもかなり遅かったので...自分で短いメソッドを書きました...:

public static int indexOfIgnoreCase(final String chkstr, final String searchStr, int i) {
    if (chkstr != null && searchStr != null && i > -1) {
          int serchStrLength = searchStr.length();
          char[] searchCharLc = new char[serchStrLength];
          char[] searchCharUc = new char[serchStrLength];
          searchStr.toUpperCase().getChars(0, serchStrLength, searchCharUc, 0);
          searchStr.toLowerCase().getChars(0, serchStrLength, searchCharLc, 0);
          int j = 0;
          for (int checkStrLength = chkstr.length(); i < checkStrLength; i++) {
                char charAt = chkstr.charAt(i);
                if (charAt == searchCharLc[j] || charAt == searchCharUc[j]) {
                     if (++j == serchStrLength) {
                           return i - j + 1;
                     }
                } else { // faster than: else if (j != 0) {
                         i = i - j;
                         j = 0;
                    }
              }
        }
        return -1;
  }

私のテストによれば、はるかに高速です(少なくともsearchStringがかなり短い場合)。改善やバグについて提案がある場合は、お知らせください...(このコードをアプリケーションで使用しているので;-)

2
phil
@Test
public void testIndexofCaseSensitive() {
    TestCase.assertEquals(-1, "abcDef".indexOf("d") );
}
2
Paul McKenzie

はい、そうだと確信しています。標準ライブラリを使用してそれを回避する1つの方法は次のとおりです。

int index = str.toUpperCase().indexOf("FOO"); 
2
Yacoby

ソースを見たところです。文字を比較するため、大文字と小文字が区別されます。

2
John Topley

最初の質問はすでに何度も回答されています。はい、String.indexOf()メソッドはすべて大文字と小文字を区別します。

ロケール依存のindexOf()が必要な場合は、 Collat​​or を使用できます。設定した強度値に応じて、大文字と小文字を区別しない比較を取得し、アクセント付きの文字をアクセントなしの文字と同じように扱うこともできます。これを行う方法の例を次に示します。

private int indexOf(String original, String search) {
    Collator collator = Collator.getInstance();
    collator.setStrength(Collator.PRIMARY);
    for (int i = 0; i <= original.length() - search.length(); i++) {
        if (collator.equals(search, original.substring(i, i + search.length()))) {
            return i;
        }
    }
    return -1;
}
1
Bernd S

要約すると、3つのソリューション:

  • toLowerCase()またはtoUpperCaseを使用する
  • apacheのStringUtilsを使用する
  • 正規表現を使用して

今、私が思っていたのはどれが最速ですか?私は平均して最初のものを推測しています。

1
max

ApacheのStringUtilsバージョンによく似たバージョンを次に示します。

public int indexOfIgnoreCase(String str, String searchStr) {
    return indexOfIgnoreCase(str, searchStr, 0);
}

public int indexOfIgnoreCase(String str, String searchStr, int fromIndex) {
    // https://stackoverflow.com/questions/14018478/string-contains-ignore-case/14018511
    if(str == null || searchStr == null) return -1;
    if (searchStr.length() == 0) return fromIndex;  // empty string found; use same behavior as Apache StringUtils
    final int endLimit = str.length() - searchStr.length() + 1;
    for (int i = fromIndex; i < endLimit; i++) {
        if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) return i;
    }
    return -1;
}
0
Ernie Thomason
 static string Search(string factMessage, string b)
        {

            int index = factMessage.IndexOf(b, StringComparison.CurrentCultureIgnoreCase);
            string line = null;
            int i = index;
            if (i == -1)
            { return "not matched"; }
            else
            {
                while (factMessage[i] != ' ')
                {
                    line = line + factMessage[i];
                    i++;
                }

                return line;
            }

        }
0
Jawwad Rafiq

通常、両方の文字列を小文字に変換することは大したことではありませんが、文字列の一部が長い場合は遅くなります。ループでこれを行うと、本当に悪いでしょう。このため、indexOfIgnoreCaseをお勧めします。

0
Jakub Vrána

しかし、それを書くのは難しくありません:

public class CaseInsensitiveIndexOfTest extends TestCase {
    public void testOne() throws Exception {
        assertEquals(2, caseInsensitiveIndexOf("ABC", "xxabcdef"));
    }

    public static int caseInsensitiveIndexOf(String substring, String string) {
        return string.toLowerCase().indexOf(substring.toLowerCase());
    }
}
0
Carl Manaster