ทดสอบว่าสตริงมีสตริงใด ๆ จากอาร์เรย์หรือไม่


153

ฉันจะทดสอบสตริงเพื่อดูว่ามันมีสตริงใด ๆ จากอาร์เรย์ได้อย่างไร

แทนที่จะใช้

if (string.contains(item1) || string.contains(item2) || string.contains(item3))

4
คุณกำลังถามว่าสตริงเท่ากับสตริงใด ๆ ในอาร์เรย์หรือมีสตริงใด ๆ จากในอาร์เรย์หรือไม่
Natix

1
คุณต้องการตรวจสอบว่าสตริงจากอาร์เรย์ใดเป็นสตริงย่อยของสตริงอินพุตของคุณหรือไม่ หรือคุณต้องการตรวจสอบว่าสตริงอินพุตของคุณเท่ากับหนึ่งในสตริงในอาร์เรย์หรือไม่ คุณจะแม่นยำมากขึ้น?
Savino Sguera

1
มีเพื่อที่จะใช้เวลาบรรทัดและเห็นว่ามันมีคำใด ๆ จากรายการ (เก็บไว้เป็นอาร์เรย์ของสตริง)
arowell

คำตอบ:


188

แก้ไข: นี่คือการปรับปรุงโดยใช้ Java 8 Streaming API ทำความสะอาดมาก ยังสามารถใช้ร่วมกับนิพจน์ปกติได้เช่นกัน

public static boolean stringContainsItemFromList(String inputStr, String[] items) {
    return Arrays.stream(items).parallel().anyMatch(inputStr::contains);
}

นอกจากนี้หากเราเปลี่ยนประเภทอินพุตเป็นรายการแทนที่จะเป็นอาร์เรย์ที่เราสามารถitems.parallelStream().anyMatch(inputStr::contains)ใช้ได้

คุณสามารถใช้.filter(inputStr::contains).findAny()หากคุณต้องการส่งคืนสตริงที่ตรงกัน


คำตอบเดิมเล็กน้อยวันที่:

นี่คือวิธีคงที่ (ขั้นพื้นฐานมาก) โปรดทราบว่ามันเป็นกรณีที่สำคัญในสตริงการเปรียบเทียบ ดั้งเดิมวิธีที่จะทำให้มันกรณีตายจะโทรtoLowerCase()หรือtoUpperCase()ทั้งเข้าและสายการทดสอบ

หากคุณต้องการทำอะไรที่ซับซ้อนกว่านี้ฉันขอแนะนำให้ดูที่คลาสPatternและMatcherและเรียนรู้วิธีการทำนิพจน์ทั่วไป เมื่อคุณเข้าใจสิ่งเหล่านั้นคุณสามารถใช้คลาสเหล่านั้นหรือString.matches()วิธีการช่วยเหลือ

public static boolean stringContainsItemFromList(String inputStr, String[] items)
{
    for(int i =0; i < items.length; i++)
    {
        if(inputStr.contains(items[i]))
        {
            return true;
        }
    }
    return false;
}

1
วิธีใช้กับนิพจน์ทั่วไป @gnomed
Praneeth

เราจะทำให้การใช้งานตัวพิมพ์เล็กและตัวพิมพ์ใหญ่เป็นเรื่องแรกได้อย่างไร?
thanos.a

การใช้งานเป็นกรณี ๆ ไปแล้ว ฉันยังมีคำแนะนำวิธีทำให้ตัวพิมพ์เล็กและตัวพิมพ์เล็กไม่ตอบสนองในย่อหน้าด้านล่างของคำตอบ
gnomed

52
import org.apache.commons.lang.StringUtils;

String Utils

ใช้:

StringUtils.indexOfAny(inputString, new String[]{item1, item2, item3})

มันจะกลับดัชนีของสตริงพบหรือ -1 ถ้าไม่พบ


7
JFI: ฉันหวังว่าการติดตั้งนี้จะวนซ้ำเพียงครั้งเดียวผ่าน inputString แต่ฉันดูโค้ดใน StringUtils และน่าเศร้าที่มันเพิ่งจะทำการเรียก N ของ indexOf เริ่มต้น
alfonx

บางทีในการใช้งานคอมมอนส์ 3 การใช้งานจะดีกว่า!
renanleandrof

1
ไม่, ยังคงทำซ้ำมากกว่า Strings ใน org.apache.commons.lang3.StringUtils: สำหรับ (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx

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


16

วิธีที่ง่ายที่สุดอาจจะเป็นการแปลงอาร์เรย์เป็น java.util.ArrayList เมื่ออยู่ในรายการอาร์เรย์คุณสามารถใช้วิธีการได้อย่างง่ายดาย

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}

70
สิ่งนี้ไม่ถูกต้อง OP จะถามว่าstringมีStrings ใด ๆในอาร์เรย์หรือไม่ถ้ามีStrings ใด ๆในอาร์เรย์ที่มีstringอยู่
Beau Grantham

3
@BeauGrantham ฉันก็คิดเช่นกัน แต่ OP ใช้.equals()ในโพสต์ของพวกเขาซึ่งทำให้สับสนมาก ฉันคิดว่าพวกเขาจำเป็นต้องแก้ไขคำถามของพวกเขา
gnomed

@BeauGrantham ผู้ชายฉันไม่สามารถสาบานว่าฉันเข้าใจปัญหา บางทีคำถามจะต้องมีการชี้แจงเพิ่มอีกนิดหรือ
รอย Kachouh

1
ไม่ทิศทางของการผกผันเช่นนี้ไม่สามารถใช้งานได้คุณควรตรวจสอบว่า String มีค่าใดค่าหนึ่งที่ระบุหรือไม่ถ้าค่าที่ให้นั้นมีสตริงอยู่
Vladimir Stazhilov

2
คำถามตรงข้าม
Stéphane GRILLON

16

หากคุณใช้Java 8หรือสูงกว่าคุณสามารถพึ่งพาStream APIเพื่อทำสิ่งนี้:

public static boolean containsItemFromArray(String inputString, String[] items) {
    // Convert the array of String items as a Stream
    // For each element of the Stream call inputString.contains(element)
    // If you have any match returns true, false otherwise
    return Arrays.stream(items).anyMatch(inputString::contains);
}

สมมติว่าคุณมีชุดStringทดสอบขนาดใหญ่จำนวนมากเพื่อทดสอบคุณสามารถเปิดการค้นหาแบบขนานโดยการโทรจากparallel()นั้นโค้ดจะเป็น:

return Arrays.stream(items).parallel().anyMatch(inputString::contains); 

สิ่งหนึ่งที่ฉันสังเกตเห็นฉันมีสองรายการในรายการสตริงฉันพบเมื่อฉันใช้ 'ขนาน' มันจะไม่ส่งคืนผลลัพธ์ที่ถูกต้อง (แม้ว่าจะมีค่า)
CharlesC

@ Charles.C มันแปลกฉันไม่สามารถทำซ้ำในด้านของฉัน
Nicolas Filotto

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

2

นี่คือทางออกหนึ่ง:

public static boolean containsAny(String str, String[] words)
{
   boolean bResult=false; // will be set, if any of the words are found
   //String[] words = {"word1", "word2", "word3", "word4", "word5"};

   List<String> list = Arrays.asList(words);
   for (String word: list ) {
       boolean bFound = str.contains(word);
       if (bFound) {bResult=bFound; break;}
   }
   return bResult;
}


1

วิธี groovyesque ที่มากขึ้นคือการใช้injectร่วมกับmetaClass :

ฉันชอบที่จะพูดว่า:

String myInput="This string is FORBIDDEN"
myInput.containsAny(["FORBIDDEN","NOT_ALLOWED"]) //=>true

และวิธีการจะเป็น:

myInput.metaClass.containsAny={List<String> notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}

หากคุณต้องการcontainsAnyที่จะนำเสนอสำหรับการใด ๆ ตัวแปร String อนาคตแล้วเพิ่มวิธีการที่จะแทนระดับของวัตถุที่:

String.metaClass.containsAny={notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}

1

ลองสิ่งนี้:

if (Arrays.asList(item1, item2, item3).stream().anyMatch(string::contains))

15
คำถามตรงข้าม: สตริงเป้าหมายมีสตริงใด ๆ ในรายการหรือไม่
Basil Bourque

1
คำถามตรงข้าม
Stéphane GRILLON

0

และหากคุณกำลังมองหาการจับคู่แบบตัวพิมพ์เล็กและใหญ่ให้ใช้รูปแบบ

Pattern pattern = Pattern.compile("\\bitem1 |item2\\b",java.util.regex.Pattern.CASE_INSENSITIVE);

    Matcher matcher = pattern.matcher(input);
    if(matcher.find() ){ 

}

0

หากคุณกำลัง seraching สำหรับทั้ง คำพูดที่คุณสามารถทำเช่นนี้ที่ทำงานกรณี ตาย

private boolean containsKeyword(String line, String[] keywords)
{
    String[] inputWords = line.split(" ");

    for (String inputWord : inputWords)
    {
        for (String keyword : keywords)
        {
            if (inputWord.equalsIgnoreCase(keyword))
            {
                return true;
            }
        }
    }

    return false;
}

0

เราสามารถทำสิ่งนี้เช่นกัน:

if (string.matches("^.*?((?i)item1|item2|item3).*$"))
(?i): used for case insensitive
.*? & .*$: used for checking whether it is present anywhere in between the string.

-3

ด้านล่างควรใช้กับคุณโดยสมมติว่าStringsคืออาร์เรย์ที่คุณกำลังค้นหาภายใน:

Arrays.binarySearch(Strings,"mykeytosearch",mysearchComparator);

โดยที่ mykeytosearch เป็นสตริงที่คุณต้องการทดสอบการมีอยู่ภายในอาเรย์ mysearchComparator - เป็นตัวเปรียบเทียบที่จะใช้ในการเปรียบเทียบสตริง

อ้างถึงArrays.binarySearchสำหรับข้อมูลเพิ่มเติม


2
ควรสังเกตว่า binarySearch ทำงานเฉพาะในอาเรย์ที่เรียงลำดับตามธรรมชาติหรือโดยตัวเปรียบเทียบที่กำหนด (ถ้ามีการระบุไว้)
Natix

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.