web-dev-qa-db-fra.com

indexOf cas sensible?

La méthode indexOf (String) est-elle sensible à la casse? Si tel est le cas, existe-t-il une version de celle-ci qui ne respecte pas la casse?

63
Brian

Les méthodes indexOf() sont toutes sensibles à la casse. Vous pouvez les rendre insensibles à la casse (en gros, de manière cassée, mais en travaillant dans de nombreux cas) en convertissant au préalable vos chaînes en majuscules/minuscules:

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

La méthode indexOf (String) est-elle sensible à la casse?

Oui, c'est sensible à la casse:

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

Si tel est le cas, existe-t-il une version de celle-ci qui ne respecte pas la casse?

Non, il n'y en a pas. Vous pouvez convertir les deux chaînes en minuscules avant d'appeler indexOf:

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

Il existe une méthode ignore case dans la classe StringUtils de la bibliothèque Apache Commons Lang

indexOfIgnoreCase (CharSequence str, CharSequence searchStr)

17
deepika

Oui, indexOf est sensible à la casse.

La meilleure façon de faire de la casse que j'ai trouvée est la suivante:

String original;
int idx = original.toLowerCase().indexOf(someStr.toLowerCase());

Cela fera une indexOf() insensible à la casse.

15
jjnguy

Voici ma solution qui n'alloue pas de mémoire heap, elle devrait donc être beaucoup plus rapide que la plupart des autres implémentations mentionnées ici.

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;
}

Et voici les tests unitaires qui vérifient le comportement correct.

@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

Oui, c'est sensible à la casse. Vous pouvez effectuer une indexOf insensible à la casse en convertissant vos paramètres String et String en majuscules avant la recherche.

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

Notez que toUpperCase peut ne pas fonctionner dans certaines circonstances. Par exemple ceci:

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

idxU aura 20 ans, ce qui est faux! idxL sera 19, ce qui est correct. Le problème est que toUpperCase () convertit le caractère "ß" en deux caractères, "SS", ce qui jette l'index hors tension.

Par conséquent, restez toujours avec toLowerCase ()

10
Nick Lewis

Que faites-vous avec la valeur d'index une fois renvoyée?

Si vous l'utilisez pour manipuler votre chaîne, vous ne pouvez pas utiliser une expression régulière à la place?

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

J'avais le même problème… .. J'ai essayé l'expression régulière et Apache StringUtils.indexOfIgnoreCase-Method, mais les deux étaient plutôt lents… .. J'ai donc écrit moi-même une courte méthode…:

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;
  }

Selon mes tests, c’est beaucoup plus rapide ... (du moins si votre chaîne de recherche est plutôt courte) . Si vous avez des suggestions d’amélioration ou des bugs, ce serait bien de me le faire savoir ... dans une application ;-)

2
phil

Pour résumer, 3 solutions:

  • en utilisant toLowerCase () ou toUpperCase
  • en utilisant StringUtils of Apache
  • en utilisant regex

Maintenant, je me demandais lequel était le plus rapide? ... Je devine en moyenne le premier.

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

Oui, j'en suis à peu près sûr. Une méthode pour contourner ce problème en utilisant la bibliothèque standard serait:

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

Je viens de regarder la source. Il compare les caractères, donc il est sensible à la casse.

2
John Topley

La première question a déjà reçu plusieurs réponses. Oui, les méthodes String.indexOf() sont toutes sensibles à la casse.

Si vous avez besoin d'une indexOf() sensible aux paramètres régionaux, vous pouvez utiliser le Collator . Selon la valeur de la force que vous définissez, vous pouvez obtenir une comparaison ne faisant pas la distinction entre les majuscules et les minuscules, mais aussi traiter les lettres accentuées comme les lettres non accentuées, etc.

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

Voici une version ressemblant beaucoup à la version de 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

La conversion des deux chaînes en minuscules n’est généralement pas un problème, mais elle serait lente si certaines chaînes étaient longues. Et si vous faites cela en boucle, ce serait vraiment mauvais. Pour cette raison, je recommanderais indexOfIgnoreCase.

0
Jakub Vrána

Mais ce n'est pas difficile d'en écrire un:

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