Kiểm tra nếu một chuỗi chứa bất kỳ chuỗi nào từ một mảng


153

Làm cách nào để kiểm tra một chuỗi để xem nó có chứa bất kỳ chuỗi nào trong một mảng không?

Thay vì sử dụng

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

4
Bạn có hỏi nếu một chuỗi bằng với bất kỳ chuỗi nào trong mảng hoặc chứa bất kỳ chuỗi nào trong mảng không?
Natix

1
Bạn muốn kiểm tra xem có bất kỳ chuỗi nào trong mảng là một chuỗi con của chuỗi đầu vào của bạn không? Hoặc bạn muốn kiểm tra xem chuỗi đầu vào của bạn có bằng một trong các chuỗi trong mảng không? Bạn có thể chính xác hơn?
Savino Sguera

1
chứa, để nó lấy một dòng và xem nó có chứa bất kỳ từ nào trong danh sách không (được lưu dưới dạng một chuỗi các chuỗi)
arowell

Câu trả lời:


187

EDIT: Đây là bản cập nhật sử dụng API phát trực tuyến Java 8. Vì vậy, sạch sẽ hơn nhiều. Vẫn có thể được kết hợp với các biểu thức thông thường quá.

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

Ngoài ra, nếu chúng ta thay đổi loại đầu vào thành Danh sách thay vì một mảng, chúng ta có thể sử dụng items.parallelStream().anyMatch(inputStr::contains).

Bạn cũng có thể sử dụng .filter(inputStr::contains).findAny()nếu bạn muốn trả về chuỗi phù hợp.


Câu trả lời ban đầu hơi ngày:

Đây là một phương thức tĩnh (RẤT CƠ BẢN). Lưu ý rằng nó là trường hợp nhạy cảm trên các chuỗi so sánh. Một cách nguyên thủy để làm cho trường hợp không nhạy cảm sẽ là gọi toLowerCase()hoặc toUpperCase()trên cả chuỗi đầu vào và chuỗi kiểm tra.

Nếu bạn cần làm bất cứ điều gì phức tạp hơn thế này, tôi khuyên bạn nên xem các lớp Mẫu và Trình so khớp và học cách thực hiện một số biểu thức thông thường. Một khi bạn hiểu những điều đó, bạn có thể sử dụng các lớp đó hoặc String.matches()phương thức của trình trợ giúp.

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
Cách sử dụng với biểu thức chính quy @gnomed
Praneeth

Làm thế nào chúng ta có thể làm cho trường hợp thực hiện đầu tiên nhạy cảm?
thanos.a

Việc thực hiện là trường hợp nhạy cảm. Tôi cũng có hướng dẫn về cách làm cho trường hợp không nhạy cảm trong các đoạn dưới cùng của câu trả lời.
viết

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

Chuỗi sử dụng

Sử dụng:

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

Nó sẽ trả về chỉ mục của chuỗi được tìm thấy hoặc -1 nếu không tìm thấy.


7
JFI: Tôi hy vọng việc triển khai này chỉ lặp lại một lần so với inputString, nhưng tôi đã xem mã trong StringUtils, và thật đáng buồn khi nó chỉ thực hiện các cuộc gọi N của indexOf mặc định.
alfonx 21/07/2015

Có lẽ trên commons3 việc thực hiện là tốt hơn!
renanleandrof

1
Không, vẫn chỉ lặp qua các Chuỗi trong org.apache.commons.lang3.StringUtils: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx

Điều này không trả về chỉ mục của chuỗi được tìm thấy (từ mảng), chỉ có chỉ mục của vị trí mà chuỗi được tìm thấy tại.
Sao Diêm Vương

33

Bạn có thể sử dụng phương thức khớp chuỗi # như thế này:

System.out.printf("Matches - [%s]%n", string.matches("^.*?(item1|item2|item3).*$"));

16

Cách dễ nhất có lẽ là chuyển đổi mảng thành java.util.ArrayList. Khi nó nằm trong một danh sách mảng, bạn có thể dễ dàng tận dụng phương thức chứa.

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

69
Điều này là không đúng. OP đang hỏi xem stringcó chứa bất kỳ Strings nào trong mảng không, nếu có bất kỳ Strings nào trong mảng chứa string.
Beau Grantham

3
@BeauGrantham Tôi cũng đã nghĩ vậy, nhưng OP đang sử dụng .equals()trong bài đăng của họ, điều này rất khó hiểu. Tôi nghĩ họ cần chỉnh sửa câu hỏi của họ
viết

@BeauGrantham Man Tôi không thể tuyên thệ tôi đã hiểu vấn đề. Có lẽ câu hỏi cần được làm rõ hơn một chút?
Roy Kachouh

1
Không, loại hướng ngược này sẽ không hoạt động, bạn nên kiểm tra xem Chuỗi có chứa MỘT trong các giá trị được cung cấp và KHÔNG nếu các giá trị đưa ra có chứa chuỗi.
Vladimir Stazhilov

2
Câu hỏi ngược lại
Stéphane GRILLON 7/12/2016

16

Nếu bạn sử dụng Java 8 trở lên, bạn có thể dựa vào API Stream để thực hiện điều đó:

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

Giả sử rằng bạn có một mảng lớn Stringđể kiểm tra, bạn cũng có thể khởi chạy tìm kiếm song song bằng cách gọi parallel(), mã sau đó sẽ là:

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

Một điều kỳ lạ tôi nhận thấy, tôi có hai mục trong danh sách Chuỗi, tôi phát hiện ra, khi tôi sử dụng 'song song', nó sẽ không trả về kết quả chính xác. (ngay cả khi nó chứa giá trị).
CharlesC

@ Charles.C Thật kỳ lạ, tôi không thể sinh sản về phía mình.
Nicolas Filotto

Tôi khá chắc chắn rằng song song luồng sẽ không tối ưu ở đây trừ khi chuỗi đầu vào dài (~ 500 ký tự). Thay vào đó nếu mảng lớn, có lẽ sẽ tốt hơn khi chia mảng và chạy song song từng mảng.
cuộc sống bất thường

2

Đây là một giải pháp:

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

Một cách tiếp cận hấp dẫn hơn sẽ là sử dụng tiêm kết hợp với metaClass :

Tôi rất muốn nói:

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

Và phương pháp sẽ là:

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

Nếu bạn cần chứaAny để có mặt cho bất kỳ biến String nào trong tương lai thì hãy thêm phương thức vào lớp thay vì đối tượng:

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


0

Và nếu bạn đang tìm kiếm trường hợp khớp không nhạy cảm, hãy sử dụng mẫu

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

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

}

0

Nếu bạn đang seraching cho toàn bộ những lời bạn có thể làm điều này mà làm việc trường hợp nhạy cảm .

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

Chúng ta cũng có thể làm như thế này:

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

Dưới đây sẽ phù hợp với bạn khi giả sử Chuỗi là mảng mà bạn đang tìm kiếm trong:

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

trong đó mykeytosearch là chuỗi mà bạn muốn kiểm tra sự tồn tại trong mảng. mysearchComparator - là một bộ so sánh sẽ được sử dụng để so sánh các chuỗi.

Tham khảo Arrays.binarySearch để biết thêm thông tin.


2
Cần lưu ý rằng binarySearch chỉ hoạt động trên mảng được sắp xếp, theo cách tự nhiên hoặc bằng bộ so sánh đã cho (nếu được đưa ra).
Natix

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.