วิธีการตรวจสอบว่าสตริงมีสตริงอื่นในกรณีที่ไม่รู้สึกตัวใน Java?


386

บอกว่าฉันมีสองสาย

String s1 = "AbBaCca";
String s2 = "bac";

ฉันต้องการที่จะดำเนินการตรวจสอบกลับมาที่อยู่ภายในs2 s1ฉันสามารถทำได้ด้วย:

return s1.contains(s2);

ฉันค่อนข้างแน่ใจว่าตัวcontains()พิมพ์เล็กและตัวพิมพ์ใหญ่ แต่ฉันไม่สามารถระบุได้อย่างแน่นอนจากการอ่านเอกสาร ถ้าเป็นเช่นนั้นฉันคิดว่าวิธีที่ดีที่สุดของฉันจะเป็นเช่น:

return s1.toLowerCase().contains(s2.toLowerCase());

ทั้งหมดนี้นอกเหนือจากนี้มีวิธีอื่น (อาจจะดีกว่า) ในการทำสิ่งนี้ให้สำเร็จโดยไม่ใส่ใจกับตัวพิมพ์เล็กหรือไม่?


DrJavaจะเป็นวิธีที่ง่ายที่สุดในการทดสอบเมื่อเอกสารล้มเหลวคุณ เพียงพิมพ์สองสามกรณีทดสอบลงในหน้าต่างการโต้ตอบและคุณควรทราบ
EfForEffort

17
ฉันคิดว่าคุณตอบคำถามของคุณเอง ฉันไม่คิดว่าวิธีการแก้ปัญหาด้านล่างจะดีกว่านี้ แต่มันช้ากว่าแน่นอน
Nikolay Dimitrov

7
วิธีการแก้ปัญหาของคุณง่ายกว่าวิธีใด ๆ ในคำตอบ
LobsterMan

2
คำตอบที่ฉันและหลายคนกำลังมองหาอยู่ในคำถามของคุณ
Lalit Fauzdar

1
ตัวอย่างของคุณเป็นวิธีที่ง่ายที่สุดอ่านได้มากที่สุดและอาจเป็นวิธีที่ดีที่สุดในการทำสิ่งนี้ - ดีกว่าคำตอบที่ฉันเห็น
user1258361

คำตอบ:


320

ใช่มีเป็นกรณี ๆ ไป คุณสามารถใช้ java.util.regex.Pattern พร้อมกับการตั้งค่าสถานะ CASE_INSENSITIVE สำหรับการจับคู่แบบคำนึงถึงขนาดตัวพิมพ์:

Pattern.compile(Pattern.quote(wantedStr), Pattern.CASE_INSENSITIVE).matcher(source).find();

แก้ไข:หาก s2 มีอักขระพิเศษ regex (ซึ่งมีจำนวนมาก) เป็นสิ่งสำคัญที่จะต้องอ้างอิงก่อน ฉันแก้ไขคำตอบของฉันแล้วเนื่องจากเป็นคนแรกที่จะเห็น แต่ลงคะแนนให้ Matt Quail เพราะเขาชี้ให้เห็น


23
ตามที่ระบุไว้ในเอกสารสำหรับPattern.CASE_INSENSITIVEสิ่งนี้ใช้ได้กับอักขระ ASCII เท่านั้น (เช่น "Ä" จะไม่ตรงกับ "ä") หนึ่งต้องระบุเพิ่มเติมUNICODE_CASEธงเพื่อบรรลุว่า
Philipp Wendler

72
วิธีนี้ใช้นักPatternแสดงมากกว่าs1.toLowerCase().contains(s2.toLowerCase())หรือเปล่า?
Rajat Gupta

6
@ user01 ฉันทำการวิเคราะห์ความเร็ว ดูคำตอบของฉันสำหรับผลลัพธ์ (ฉันยังแสดงวิธีแก้ปัญหาที่เร็วขึ้น): stackoverflow.com/a/25379180/1705598
icza

10
ฉันจะชัดเจนยิ่งขึ้นว่าเกิดอะไรขึ้นถ้าเรามีชื่อตัวแปรที่ดีกว่า:Pattern.compile(Pattern.quote(needle), Pattern.CASE_INSENSITIVE).matcher(haystack).find()
John Bowers

5
ความถูกต้อง @ user01 มาก่อนการปฏิบัติงานและการใช้ toLowerCase จะให้ผลลัพธ์ที่ไม่ถูกต้อง (ตัวอย่างเช่นเมื่อเปรียบเทียบข้อความภาษากรีกบางข้อความที่มีตัวอักษรซิกมาซึ่งมีสองรูปแบบตัวพิมพ์เล็กสำหรับฟอร์มตัวพิมพ์ใหญ่เดียวกัน)
Klitos Kyriacou

266

ปัญหาหนึ่งที่คำตอบของ Dave L.คือเมื่อ s2 มีมาร์กอัป regex เช่น\dฯลฯ

คุณต้องการโทรหา Pattern.quote () ที่ s2:

Pattern.compile(Pattern.quote(s2), Pattern.CASE_INSENSITIVE).matcher(s1).find();

1
จับแมตต์ได้ดี ฉันอยากรู้ว่าวิธีการใดมีประสิทธิภาพมากกว่า - ตัวพิมพ์เล็กหรือโซลูชันของคุณ การใช้รูปแบบมีประสิทธิภาพน้อยกว่าสำหรับการเปรียบเทียบแบบเดี่ยว แต่มีประสิทธิภาพมากกว่าสำหรับการเปรียบเทียบหลายรายการหรือไม่
แอรอน

41
กระบวนการ. toLowerCase (). contain () อาจจะเร็วกว่าในกรณีส่วนใหญ่ ฉันอาจจะชอบสไตล์นั้นเพื่อลดความซับซ้อนลงเช่นกัน
Matt Quail

3
@AaronFerguson ใช่แน่นอนtoLowerCase().contains()เร็วกว่า ฉันทำการวิเคราะห์ความเร็วดูคำตอบสำหรับผลลัพธ์ของฉัน: stackoverflow.com/a/25379180/1705598
icza

2
@ MattQuail ไม่มีจุดใดที่จะเร็วขึ้นถ้ามันไม่ถูกต้อง ตัวอย่างเช่น sigma capital กรีกมีรูปแบบตัวพิมพ์เล็กสองแบบ (ขึ้นอยู่กับว่าท้ายคำหรือไม่) และเมื่อพยายามทำการจับคู่สตริงย่อยแบบไม่คำนึงถึงขนาดตัวพิมพ์โดยที่สตริงย่อยลงท้ายด้วย sigma คุณอาจผิดพลาดได้อย่างง่ายดาย ผล.
Klitos Kyriacou

ฉันคิดว่าเราควรเพิ่มการPattern.UNICODE_CASEตั้งค่าสถานะด้วย คุณกรุณายืนยันสิ่งนี้ได้ไหม
Thariq Nugrohotomo

160

คุณสามารถใช้ได้

org.apache.commons.lang3.StringUtils.containsIgnoreCase("AbBaCca", "bac");

Apache Commonsห้องสมุดเป็นประโยชน์อย่างมากสำหรับการจัดเรียงของสิ่งนี้ และอันนี้อาจจะดีกว่าการแสดงออกปกติเพราะ regex มีราคาแพงในแง่ของประสิทธิภาพเสมอ


1
มีใครรู้บ้างไหมว่าเรื่องนี้เกี่ยวกับสถานที่เกิดเหตุ?
Charles Wood

12
@CharlesWood มันมอบหมายให้String.regionMatchesซึ่งใช้การแปลงตัวอักษรฉลาดดังนั้นไม่ ยิ่งกว่านั้นcontainsIgnoreCase("ß", "ss")จะส่งคืน -1 ซึ่งเป็นสิ่งผิดในทุกภาษา (ภาษาเยอรมัน "sharp s" เปลี่ยนเป็น "ss" เป็นภาษาเยอรมัน)
maaartinus

ซึ่งจะเป็นวิธีที่เหมาะสมในการเปรียบเทียบคำภาษาเยอรมันแล้ว ดูเหมือนว่าเป็นภาษาเดียวที่ทำให้การเปรียบเทียบสตริงมีความซับซ้อนทุกวิธี: P
chomp

1
BTW: ภาษาเยอรมันที่ยื่นออกมาอย่างเป็นทางการกับเอสเอสในปี 2017 เงินทุน: de.wikipedia.org/wiki/Gro%C3%9Fes_%C3%9F สำหรับแป้นพิมพ์ภาษาเยอรมันให้พิมพ์ Shift + Alt Gr + ß -> test: ẞ😁
Kawu

119

การใช้งานที่เร็วขึ้น: การใช้ประโยชน์ String.regionMatches()

การใช้ regexp นั้นค่อนข้างช้า (ช้า) มันไม่สำคัญว่าคุณแค่ต้องการเช็คอินหนึ่งกรณี แต่ถ้าคุณมีอาเรย์หรือชุดของพันหรือร้อยเป็นพันของสตริงสิ่งต่าง ๆ อาจช้าลงได้

โซลูชันที่นำเสนอด้านล่างไม่ใช้นิพจน์ทั่วไปหรือtoLowerCase()(ซึ่งช้าเช่นกันเพราะสร้างสตริงใหม่และเพิ่งโยนทิ้งหลังจากเช็ค)

โซลูชันสร้างบนเมธอด String.regionMatches ()ซึ่งดูเหมือนจะไม่เป็นที่รู้จัก มันตรวจสอบว่า 2 Stringภูมิภาคตรงกันหรือไม่ แต่ที่สำคัญคือมันมีโอเวอร์โหลดพร้อมignoreCaseพารามิเตอร์ที่ใช้งานสะดวก

public static boolean containsIgnoreCase(String src, String what) {
    final int length = what.length();
    if (length == 0)
        return true; // Empty string is contained

    final char firstLo = Character.toLowerCase(what.charAt(0));
    final char firstUp = Character.toUpperCase(what.charAt(0));

    for (int i = src.length() - length; i >= 0; i--) {
        // Quick check before calling the more expensive regionMatches() method:
        final char ch = src.charAt(i);
        if (ch != firstLo && ch != firstUp)
            continue;

        if (src.regionMatches(true, i, what, 0, length))
            return true;
    }

    return false;
}

การวิเคราะห์ความเร็ว

การวิเคราะห์ความเร็วนี้ไม่ได้หมายถึงวิทยาศาสตร์จรวด แต่เป็นเพียงภาพคร่าวๆของวิธีการที่แตกต่างกันอย่างรวดเร็ว

ฉันเปรียบเทียบ 5 วิธี

  1. เราcontainsIgnoreCase ()วิธีการ
  2. String.contains()โดยการแปลงสตริงทั้งสองจะลดกรณีและโทร
  3. โดยการแปลงสตริงซอร์สให้เป็นตัวพิมพ์เล็กและโทรString.contains()ด้วยสตริงย่อยที่แคชไว้ล่วงหน้าและต่ำกว่า วิธีนี้ไม่ยืดหยุ่นเท่าที่ควรเพราะจะทำการทดสอบ substring ที่ต้องการ
  4. ใช้การแสดงออกปกติ (คำตอบที่ยอมรับPattern.compile().matcher().find()... )
  5. โดยใช้การแสดงออกปกติ Patternแต่มีการสร้างไว้ล่วงหน้าและเก็บไว้ชั่วคราว วิธีการแก้ปัญหานี้มีความยืดหยุ่นไม่ได้เพราะมันทดสอบ substring ที่กำหนดไว้ล่วงหน้า

ผลลัพธ์ (โดยเรียกวิธีการ 10 ล้านครั้ง):

  1. วิธีการของเรา: 670 มิลลิวินาที
  2. 2x toLowerCase () และมี (): 2829 ms
  3. 1x toLowerCase () และประกอบด้วย () พร้อมสตริงย่อยที่เก็บไว้: 2446 ms
  4. Regexp: 7180 มิลลิวินาที
  5. Regexp ด้วยแคชPattern: 1845 ms

ผลลัพธ์ในตาราง:

                                            RELATIVE SPEED   1/RELATIVE SPEED
 METHOD                          EXEC TIME    TO SLOWEST      TO FASTEST (#1)
------------------------------------------------------------------------------
 1. Using regionMatches()          670 ms       10.7x            1.0x
 2. 2x lowercase+contains         2829 ms        2.5x            4.2x
 3. 1x lowercase+contains cache   2446 ms        2.9x            3.7x
 4. Regexp                        7180 ms        1.0x           10.7x
 5. Regexp+cached pattern         1845 ms        3.9x            2.8x

วิธีการของเราคือ4x เร็วขึ้นเมื่อเทียบกับ lowercasing และการใช้contains(), 10x ได้เร็วขึ้นเมื่อเทียบกับการใช้นิพจน์ปกติและยัง3x เร็วขึ้นแม้ว่าPatternเป็นแคชล่วงหน้า (และการสูญเสียความยืดหยุ่นของการตรวจสอบการย่อยโดยพล)


รหัสทดสอบการวิเคราะห์

หากคุณสนใจว่าจะทำการวิเคราะห์อย่างไรต่อไปนี้เป็นแอปพลิเคชันที่รันได้สมบูรณ์แบบ:

import java.util.regex.Pattern;

public class ContainsAnalysis {

    // Case 1 utilizing String.regionMatches()
    public static boolean containsIgnoreCase(String src, String what) {
        final int length = what.length();
        if (length == 0)
            return true; // Empty string is contained

        final char firstLo = Character.toLowerCase(what.charAt(0));
        final char firstUp = Character.toUpperCase(what.charAt(0));

        for (int i = src.length() - length; i >= 0; i--) {
            // Quick check before calling the more expensive regionMatches()
            // method:
            final char ch = src.charAt(i);
            if (ch != firstLo && ch != firstUp)
                continue;

            if (src.regionMatches(true, i, what, 0, length))
                return true;
        }

        return false;
    }

    // Case 2 with 2x toLowerCase() and contains()
    public static boolean containsConverting(String src, String what) {
        return src.toLowerCase().contains(what.toLowerCase());
    }

    // The cached substring for case 3
    private static final String S = "i am".toLowerCase();

    // Case 3 with pre-cached substring and 1x toLowerCase() and contains()
    public static boolean containsConverting(String src) {
        return src.toLowerCase().contains(S);
    }

    // Case 4 with regexp
    public static boolean containsIgnoreCaseRegexp(String src, String what) {
        return Pattern.compile(Pattern.quote(what), Pattern.CASE_INSENSITIVE)
                    .matcher(src).find();
    }

    // The cached pattern for case 5
    private static final Pattern P = Pattern.compile(
            Pattern.quote("i am"), Pattern.CASE_INSENSITIVE);

    // Case 5 with pre-cached Pattern
    public static boolean containsIgnoreCaseRegexp(String src) {
        return P.matcher(src).find();
    }

    // Main method: perfroms speed analysis on different contains methods
    // (case ignored)
    public static void main(String[] args) throws Exception {
        final String src = "Hi, I am Adam";
        final String what = "i am";

        long start, end;
        final int N = 10_000_000;

        start = System.nanoTime();
        for (int i = 0; i < N; i++)
            containsIgnoreCase(src, what);
        end = System.nanoTime();
        System.out.println("Case 1 took " + ((end - start) / 1000000) + "ms");

        start = System.nanoTime();
        for (int i = 0; i < N; i++)
            containsConverting(src, what);
        end = System.nanoTime();
        System.out.println("Case 2 took " + ((end - start) / 1000000) + "ms");

        start = System.nanoTime();
        for (int i = 0; i < N; i++)
            containsConverting(src);
        end = System.nanoTime();
        System.out.println("Case 3 took " + ((end - start) / 1000000) + "ms");

        start = System.nanoTime();
        for (int i = 0; i < N; i++)
            containsIgnoreCaseRegexp(src, what);
        end = System.nanoTime();
        System.out.println("Case 4 took " + ((end - start) / 1000000) + "ms");

        start = System.nanoTime();
        for (int i = 0; i < N; i++)
            containsIgnoreCaseRegexp(src);
        end = System.nanoTime();
        System.out.println("Case 5 took " + ((end - start) / 1000000) + "ms");
    }

}

6
+1 แต่โปรดทราบว่ามันล้มเหลวสำหรับß(ชาร์ปภาษาเยอรมัน S; พิมพ์ใหญ่ถึงSS) และสำหรับอักขระอื่น ๆ (ดูที่มาString.regionMatchesซึ่งพยายามแปลงทั้งสองแบบ)
maaartinus

2
คุณทดสอบสตริงเดียวกันเสมอซึ่งไม่ใช่การเปรียบเทียบที่ยุติธรรม 'i am' จะอยู่ตรงกลางเสมอซึ่งอาจจะใช่หรือไม่ใช่สร้างความแตกต่างให้กับวิธีการค้นหาที่แตกต่างกัน ดีกว่าคือการสร้างสตริงแบบสุ่มและรายงานความเร็วเมื่อไม่มีสตริงย่อย

2
ดูเหมือนว่าจะใกล้เคียงกับวิธี Apache StringUtils: grepcode.com/file/repo1.maven.org/maven2/org.apache.commons/ …
alain.janinm

1
@ alain.janinm ฉันไม่เห็นความคล้ายคลึงกัน สิ่งเดียวที่ดูเหมือนว่า "ปิด" ด้วยStringUtils.containsIgnoreCase()คือทั้งสองวิธีการแก้ปัญหาของฉันและอาปาเช่หนึ่งใช้regionMatches()วิธีการ (ในวงจร) แต่แม้ที่ไม่เหมือนกันที่ผมเรียกและบริการโทรString.regionMatches() Apache CharSequenceUtils.regionMatches()
icza

2
@icza CharSequenceUtils.regionMatchesเพียงแค่โทรString.regionMatchesจริง อย่างไรก็ตามจุดของฉันคือการให้ข้อมูลว่าถ้าใครบางคนกำลังใช้ StringUtils lib อยู่แล้วเขาก็สามารถเรียกมันได้เพราะมันดูเหมือนจะเป็นวิธีที่มีประสิทธิภาพเหมือนกับที่คุณพิสูจน์ด้วยเกณฑ์มาตรฐานของคุณ หากฉันไม่ได้ใช้ Apache lib ฉันจะใช้วิธีการของคุณอย่างแน่นอน;)
alain.janinm

22

วิธีที่ง่ายกว่าในการทำเช่นนี้ (โดยไม่ต้องกังวลกับการจับคู่รูปแบบ) จะแปลงทั้งสองStringเป็นตัวพิมพ์เล็ก:

String foobar = "fooBar";
String bar = "FOO";
if (foobar.toLowerCase().contains(bar.toLowerCase()) {
    System.out.println("It's a match!");
}

4
กรณีตัวอักษรขึ้นอยู่กับภาษาซึ่งหมายความว่ามันจะทำงานบนคอมพิวเตอร์ของคุณ แต่จะล้มเหลวสำหรับลูกค้า :) เห็นความคิดเห็น @Adriaan Koster
kroiz

1
@kroiz ขึ้นอยู่กับว่า String มาจากไหน การเปรียบเทียบ "foobar" และ "FOO" จะจับคู่เสมออย่างไรก็ตามหากคุณกำลังเปรียบเทียบข้อมูลที่ผู้ใช้ป้อนเข้าหรือเนื้อหาเฉพาะภาษาคุณก็ถือว่าถูกต้อง - นักพัฒนาควรระมัดระวัง
Phil

16

ใช่สามารถทำได้:

String s1 = "abBaCca";
String s2 = "bac";

String s1Lower = s1;

//s1Lower is exact same string, now convert it to lowercase, I left the s1 intact for print purposes if needed

s1Lower = s1Lower.toLowerCase();

String trueStatement = "FALSE!";
if (s1Lower.contains(s2)) {

    //THIS statement will be TRUE
    trueStatement = "TRUE!"
}

return trueStatement;

รหัสนี้จะส่งคืนสตริง "TRUE!" ตามที่พบว่าตัวละครของคุณมีอยู่


12
ข้อเสียเปรียบอย่างมากของการใช้ toLowerCase () คือผลลัพธ์ขึ้นอยู่กับ Locale ปัจจุบัน ดู: javapapers.com/core-java/ …
Adriaan Koster

4
s2คำถามที่จริงมีทางออกที่ดีกว่าเป็นหนึ่งในนี้ล้มเหลวไม่ใช่ตัวพิมพ์เล็ก ไม่พูดเกี่ยวกับรายละเอียดเช่นว่าอันนี้ไม่ได้รวบรวมและถ้ามันได้มันก็จะส่งกลับสตริง
maaartinus


3

นี่คือบางอย่างที่เป็นมิตรกับ Unicode ที่คุณสามารถทำได้ถ้าคุณดึงใน ICU4j ฉันเดาว่า "ไม่สนใจขนาดตัวพิมพ์ใหญ่" เป็นคำถามที่น่าสงสัยสำหรับชื่อเมธอดเนื่องจากแม้ว่าการเปรียบเทียบความแข็งแรงหลักจะไม่สนใจตัวพิมพ์เล็ก - ใหญ่ แต่หวังว่ามันจะขึ้นอยู่กับสถานที่ในแบบที่ผู้ใช้คาดหวัง

public static boolean containsIgnoreCase(String haystack, String needle) {
    return indexOfIgnoreCase(haystack, needle) >= 0;
}

public static int indexOfIgnoreCase(String haystack, String needle) {
    StringSearch stringSearch = new StringSearch(needle, haystack);
    stringSearch.getCollator().setStrength(Collator.PRIMARY);
    return stringSearch.first();
}

3

ฉันทดสอบเพื่อค้นหาการจับคู่แบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ของสตริง ฉันมีเวกเตอร์วัตถุ 150,000 ชิ้นทั้งหมดที่มีสตริงเป็นหนึ่งฟิลด์และต้องการค้นหาชุดย่อยที่ตรงกับสตริง ฉันลองสามวิธี:

  1. แปลงเป็นตัวพิมพ์เล็กทั้งหมด

    for (SongInformation song: songs) {
        if (song.artist.toLowerCase().indexOf(pattern.toLowercase() > -1) {
                ...
        }
    }
  2. ใช้วิธีการจับคู่สตริง ()

    for (SongInformation song: songs) {
        if (song.artist.matches("(?i).*" + pattern + ".*")) {
        ...
        }
    }
  3. ใช้นิพจน์ทั่วไป

    Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher("");
    for (SongInformation song: songs) {
        m.reset(song.artist);
        if (m.find()) {
        ...
        }
    }

ผลลัพธ์เวลา:

  • ไม่มีความพยายามที่ตรงกัน: 20 msecs

  • ในการลดการจับคู่: 182 มิลลิวินาที

  • การจับคู่สตริง: 278 msecs

  • นิพจน์ทั่วไป: 65 msecs

การแสดงออกปกติดูเหมือนจะเร็วที่สุดสำหรับกรณีการใช้งานนี้


ดีที่คุณใส่ผลลัพธ์เวลา ทุกคนบอกว่า regex ช้าแค่ไหน แต่ในความเป็นจริงมันเร็วมากถ้าคุณต้องคอมไพล์ regex เพียงครั้งเดียว
woot

1

มีวิธีรัดกุมอย่างง่ายโดยใช้การตั้งค่าสถานะ regex (case insensitive {i}):

 String s1 = "hello abc efg";
 String s2 = "ABC";
 s1.matches(".*(?i)"+s2+".*");

/*
 * .*  denotes every character except line break
 * (?i) denotes case insensitivity flag enabled for s2 (String)
 * */

0

ฉันไม่แน่ใจว่าคำถามหลักของคุณคืออะไรที่นี่ แต่ใช่.


0
String container = " Case SeNsitive ";
String sub = "sen";
if (rcontains(container, sub)) {
    System.out.println("no case");
}

public static Boolean rcontains(String container, String sub) {

    Boolean b = false;
    for (int a = 0; a < container.length() - sub.length() + 1; a++) {
        //System.out.println(sub + " to " + container.substring(a, a+sub.length()));
        if (sub.equalsIgnoreCase(container.substring(a, a + sub.length()))) {
            b = true;
        }
    }
    return b;
}

โดยทั่วไปมันเป็นวิธีการที่ใช้สองสาย มันควรจะเป็นรุ่นที่มีความอ่อนไหว () เมื่อใช้เมธอด contain คุณต้องการดูว่ามีสตริงหนึ่งอยู่ในอีกสตริงหนึ่งหรือไม่

วิธีนี้ใช้สตริงที่เป็น "sub" และตรวจสอบว่าเท่ากับ substrings ของสตริงคอนเทนเนอร์ที่มีความยาวเท่ากับ "sub" หากคุณดูที่forลูปคุณจะเห็นว่าวนซ้ำในสตริงย่อย (นั่นคือความยาวของ "sub") เหนือสตริงคอนเทนเนอร์

การวนซ้ำแต่ละครั้งจะตรวจสอบเพื่อดูว่าสตริงย่อยของสตริงคอนเทนเนอร์นั้นอยู่equalsIgnoreCaseที่ย่อยหรือไม่


โดยทั่วไปมันเป็นวิธีการที่ใช้สองสาย มันควรจะเป็นกรณีที่มีรุ่นที่มีความสำคัญไม่ได้มี () เมื่อใช้เมธอด contain คุณต้องการดูว่ามีสตริงหนึ่งอยู่ในอีกสตริงหนึ่งหรือไม่ วิธีนี้ใช้สตริงที่เป็น "sub" และตรวจสอบว่าเท่ากับสตริงย่อยของสตริงคอนเทนเนอร์ที่มีความยาวเท่ากับ "sub" หากคุณดูวนรอบสำหรับคุณจะเห็นว่ามันวนซ้ำสตริงย่อย (นั่นคือความยาวของ "ย่อย") เหนือสตริงภาชนะ การวนซ้ำแต่ละครั้งจะตรวจสอบว่าสตริงย่อยของสตริงคอนเทนเนอร์เท่ากับหรือไม่เป็นสตริงย่อย
seth

@ คุณน่าจะเพิ่มคำตอบของคุณลงไป
The Guy with The Hat

2
นี่เป็นวิธีที่ช้าที่สุดเท่าที่เคยมีมา ... และก็ล้มเหลวสำหรับคนเยอรมันด้วย
maaartinus

0

หากคุณต้องค้นหาสตริง ASCII ในสตริง ASCII อื่นเช่นURLคุณจะพบว่าโซลูชันของฉันดีกว่า ฉันได้ทดสอบวิธีของ icza และใช้ความเร็วแล้วนี่คือผลลัพธ์:

  • กรณีที่ 1 ใช้เวลา 2,788 ms - regionMatches
  • กรณีที่ 2 ใช้เวลา 1520 มิลลิวินาที - ของฉัน

รหัส:

public static String lowerCaseAscii(String s) {
    if (s == null)
        return null;

    int len = s.length();
    char[] buf = new char[len];
    s.getChars(0, len, buf, 0);
    for (int i=0; i<len; i++) {
        if (buf[i] >= 'A' && buf[i] <= 'Z')
            buf[i] += 0x20;
    }

    return new String(buf);
}

public static boolean containsIgnoreCaseAscii(String str, String searchStr) {
    return StringUtils.contains(lowerCaseAscii(str), lowerCaseAscii(searchStr));
}

0
import java.text.Normalizer;

import org.apache.commons.lang3.StringUtils;

public class ContainsIgnoreCase {

    public static void main(String[] args) {

        String in = "   Annulée ";
        String key = "annulee";

        // 100% java
        if (Normalizer.normalize(in, Normalizer.Form.NFD).replaceAll("[\\p{InCombiningDiacriticalMarks}]", "").toLowerCase().contains(key)) {
            System.out.println("OK");
        } else {
            System.out.println("KO");
        }

        // use commons.lang lib
        if (StringUtils.containsIgnoreCase(Normalizer.normalize(in, Normalizer.Form.NFD).replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""), key)) {
            System.out.println("OK");
        } else {
            System.out.println("KO");
        }

    }

}

ขอบคุณสำหรับข้อมูลโค้ดนี้ซึ่งอาจให้ความช่วยเหลือระยะสั้นแบบ จำกัด คำอธิบายที่เหมาะสมจะช่วยเพิ่มมูลค่าในระยะยาวได้อย่างมากโดยการแสดงว่าเหตุใดจึงเป็นวิธีแก้ปัญหาที่ดีและจะทำให้มีประโยชน์มากขึ้นสำหรับผู้อ่านในอนาคตด้วยคำถามอื่น ๆ ที่คล้ายกัน โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายรวมถึงข้อสมมติฐานที่คุณทำ
Toby Speight

0
"AbCd".toLowerCase().contains("abcD".toLowerCase())

2
คุณสามารถปรับปรุงคำตอบของคุณโดยอธิบายว่ารหัสของคุณแก้ไขปัญหาได้อย่างไร
Isuka

1
คำตอบนี้ได้รับการแนะนำในหลาย ๆ คำตอบที่มีรายละเอียดมากขึ้นสำหรับคำถามนี้ที่คนอื่นได้ให้ไว้ ฉันไม่คิดว่าคำตอบนี้มีจุดประสงค์ที่นี่
DaveyDaveDave

0

เราสามารถใช้สตรีมกับ anyMatch และมี Java 8

public class Test2 {
    public static void main(String[] args) {

        String a = "Gina Gini Protijayi Soudipta";
        String b = "Gini";

        System.out.println(WordPresentOrNot(a, b));
    }// main

    private static boolean WordPresentOrNot(String a, String b) {
    //contains is case sensitive. That's why change it to upper or lower case. Then check
        // Here we are using stream with anyMatch
        boolean match = Arrays.stream(a.toLowerCase().split(" ")).anyMatch(b.toLowerCase()::contains);
        return match;
    }

}

0

หรือคุณสามารถใช้วิธีการง่าย ๆ และเพียงแค่แปลงกรณีของสตริงเป็นกรณีย่อยของสตริงและจากนั้นใช้มีวิธีการ



-1

คุณสามารถทำสิ่งนี้ได้ง่ายๆ:

String s1 = "AbBaCca";
String s2 = "bac";
String toLower = s1.toLowerCase();
return toLower.contains(s2);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.