簡體   English   中英

如何檢查字符串的ArrayList是否包含另一個字符串ArrayList的子字符串?

[英]How to check if an ArrayList of Strings contains substrings of another ArrayList of Strings?

List<String> actualList = Arrays.asList ("mother has chocolate", "father has dog");
List<String> expectedList = Arrays.asList ("mother", "father", "son", "daughter");

有沒有辦法檢查expectedList包含actualList字符串的任何子字符串?

我找到了一個嵌套的for-each解決方案:

public static boolean hasAny(List<String> actualList, List<String> expectedList) {
    for (String expected: expectedList)
        for (String actual: actualList)
            if (actual.contains(expected))
                return true;

    return false;
}

我試圖尋找lambda解決方案,但我不能。 我找到的所有方法都檢查String#equals而不是String#contains

有這樣的東西會很高興:

CollectionsUtils.containsAny(actualList, exptectedList);

但它使用String#equals而不是String#contains來比較字符串。

編輯:

基於問題:如果來自actualList的所有subStrings都是expectedList的一部分,我想得到TRUE。 以下凱文的解決方案適合我。

這樣的事情怎么樣:

list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2)))

在線嘗試。

  • allMatch將檢查一切是否true
  • anyMatch將檢查至少有一個是否為true

這里有類似Java 7風格的東西,沒有lambdas和流,可以更好地理解發生的事情:

boolean allMatch = true;       // Start allMatch at true
for(String s1 : list1){
  boolean anyMatch = false;    // Start anyMatch at false inside the loop
  for(String s2 : list2){
    anyMatch = s1.contains(s2);// If any contains is true, anyMatch becomes true as well
    if(anyMatch)               // And stop the inner loop as soon as we've found a match
      break;
  }
  allMatch = anyMatch;         // If any anyMatch is false, allMatch becomes false as well
  if(!allMatch)                // And stop the outer loop as soon as we've found a mismatch
    break;
}
return allMatch;

在線嘗試。


如果您希望擁有CollectionsUtils.containsAny(list1, list2)您可以在代碼中的其他地方重用,您可以自己創建一個:

public final class CollectionsUtil{
  public static boolean containsAny(ArrayList<String> list1, ArrayList<String> list2){
    return list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2)));
    // Or the contents of the Java 7 check-method above if you prefer it
  }

  private CollectionsUtil(){
    // Util class, so it's not initializable
  }
}

然后可以根據需要使用它:

boolean result = CollectionsUtils.containsAny(actualList, expectedList);

在線嘗試。

我99%肯定你是不是在找hasAny喜歡這里的大多數upvoted答案,而是要看看是否全部來自expectedList都包含在所有的字符串actualList 為此,首先創建一個Set和work的工作是有益的(因為對於HashSet contains O(1)並且對於ListO(n)相對)。

現在考慮一下,因為你想要的只是contains ,你可以分割那個actualList並從中創建唯一的單詞:

private static boolean test(List<String> actualList, List<String> expectedList) {

    Pattern p = Pattern.compile("\\s+");

    Set<String> set = actualList.stream()
            .flatMap(p::splitAsStream)
            .collect(Collectors.toSet());

    return expectedList.stream().allMatch(set::contains);

}
public static boolean containsAny(List<String> actualList, List<String> expectedList) {
    final Pattern words = Pattern.compile("\\s+");
    return actualList.stream()
                     .flatMap(words::splitAsStream)
                     .distinct()
//                     .allMatch(expectedList::contains)
                     .anyMatch(expectedList::contains);
}

Kevin的答案更好,但另一種方法是覆蓋Wrapper對象的equals方法。

import org.springframework.util.CollectionUtils;

class Holder {
    public String obj;

    public Holder(String obj) {
        this.obj = obj;
    }

    @Override
    public boolean equals(Object holder) {
        if (!(holder instanceof Holder))
            return false;

        Holder newH = ((Holder) holder);

        if (newH == null || newH.obj == null || obj == null)
            return false;

        return obj.contains(newH.obj) || newH.obj.contains(obj);  //actually it's should be one directed.
    }
}

CollectionUtils.containsAny(
            actual.stream().map(Holder::new).collect(Collectors.toList()),
            expected.stream().map(Holder::new).collect(Collectors.toList())
    );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM