سؤال

هو indexOf(سلسلة) طريقة القضية الحساسة ؟ إذا كان الأمر كذلك ، هل هناك قضية حساسة نسخة من ذلك ؟

هل كانت مفيدة؟

المحلول

ال indexOf() الطرق هي كل حساسة لحالة الأحرف. يمكنك أن تجعلها (تقريبا، بطريقة معرقة، ولكن العمل من أجل الكثير من الحالات) غير حساسة لحالة الأحرف من خلال تحويل سلاسلك إلى الحالة العلوية / الأدنى مسبقا:

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

نصائح أخرى

هل طريقة indexof (سلسلة) حساسة لحالة الأحرف؟

نعم، إنها حساسة لحالة الأحرف:

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

هناك طريقة حالات التجاهل في فئة Strututils من مكتبة Apache Commons Lang

indexofignorecase (Straightion Str، SearchStr التالي)

نعم، indexOf حاله حساسه.

أفضل طريقة للقيام بشهادة الحالات وجدت هي:

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

من شأنها أن تفعل حالة حساسة indexOf().

فيما يلي حلاي الذي لا يخصص أي ذاكرة كومة، لذلك يجب أن يكون أسرع بكثير من معظم التطبيقات الأخرى المذكورة هنا.

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

نعم، إنها حساسة لحالة الأحرف. يمكنك القيام بحالة جيدة indexOf عن طريق تحويل السلسلة الخاصة بك ومعلمة السلسلة إلى الحالة العلوية قبل البحث.

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، وهو صحيح. ما يسبب المشكلة هو Tha Touppercase () يحول حرف "ß" إلى حرفين، "SS" وهذا يلقي الفهرس.

وبالتالي، دائما عصا مع tolowercase ()

ماذا تفعل مع قيمة الفهرس مرة واحدة عاد؟

إذا كنت تستخدمه لمعالجة السلسلة الخاصة بك، فلا يمكنك استخدام تعبير منتظم بدلا من ذلك؟

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

لقد نظرت للتو إلى المصدر. يقارن الأحفير بحيث تكون حساسة لحالة الأحرف.

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

نعم، أنا متأكد من حد ما. طريقة واحدة للعمل حولها باستخدام المكتبة القياسية ستكون:

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

كان نفس المشكلة. حاولت التعبير العادي و APACHT STRESTILS.Indexofignorecase، لكن كلاهما كان بطيئا جدا ... لذلك كتبت طريقة قصيرة نفسي ...:

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 الخاص بك قصير إلى حد ما). إذا كان لديك أي اقتراحات للتحسين أو الأخطاء، فسيكون من الجيد السماح لي أن أعرف ... (منذ أن استخدم هذا الرمز في تطبيق ؛-)

تم بالفعل الرد على السؤال الأول عدة مرات. نعم، String.indexOf() الطرق هي كل حساسة لحالة الأحرف.

إذا كنت بحاجة إلى حساس لغة indexOf() يمكنك استخدام مجرور. وبعد اعتمادا على قيمة القوة التي تحددها، يمكنك الحصول على مقارنة غير حساسة للحالة، ويعالج أيضا رسائل معلمة كما هي نفسها غير معلمة، إلخ. هنا مثال على كيفية القيام بذلك:

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

فقط باختصار ، 3 حلول:

  • باستخدام toLowerCase() أو toUpperCase
  • باستخدام StringUtils أباتشي
  • باستخدام التعابير المنطقية

الآن, ما كنت أتساءل هو واحد الذي هو الأسرع ؟ انا التخمين على متوسط أول واحد.

لكن ليس من الصعب كتابة واحدة:

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

إن تحويل كلتا السلاسل إلى الحالة الصغيرة لا يكون عادة مشكلة كبيرة ولكن سيكون بطيئا إذا كانت بعض السلاسل طويلة. وإذا قمت بذلك في حلقة، فستكون سيئة للغاية. لهذا السبب، أود أن أوصى indexOfIgnoreCase.

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

        }

إليك إصدار يشبه إصدار Strutils Abache عن كثب:

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

indexof حساسة لحالة الأحرف. هذا لأنه يستخدم الطريقة المساواة لمقارنة العناصر في القائمة. الشيء نفسه يذهب إلى يحتوي على وإزالة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top