简体   繁体   English

如何检查列表是否包含Java中给定顺序的子列表

[英]How to check if a list contains a sublist in a given order in Java

I read in groovy how to check if a list contains a sublist - stackoverflow . 我在groovy中读到如何检查列表是否包含子列表 - stackoverflow

I am interested if there is a way of checking whether list contains sublist, but in a given order. 我感兴趣的是,有一种方法可以检查列表是否包含子列表,但是按给定的顺序。 For example, this code will give true , 例如,这段代码将给出真实的

    List<String> list = Arrays.asList("PRP", "VBP", "VBN", "NN", "NNS", "MD", "VB");
    List<String> sublist = Arrays.asList("MD", "VB", "VBN");
    System.out.println(list.containsAll(sublist));

But I want to get false back. 但是,我想回来。

You can use method Collections.indexOfSubList . 您可以使用方法Collections.indexOfSubList

Returns the starting position of the first occurrence of the specified target list within the specified source list, or -1 if there is no such occurrence. 返回指定源列表中指定目标列表第一次出现的起始位置,如果不存在,则返回-1 More formally, returns the lowest index i such that source.subList(i, i+target.size()).equals(target) , or -1 if there is no such index. 更正式地,返回最低索引i,使得source.subList(i, i+target.size()).equals(target) ,或者如果没有这样的索引则返回-1 (Returns -1 if target.size() > source.size() .) (如果target.size() > source.size()则返回-1 。)

int index=Collections.indexOfSubList(list , sublist);

SHORT: 短:
If Collections.indexOfSubList(list , sublist) =! -1 如果Collections.indexOfSubList(list , sublist) =! -1 Collections.indexOfSubList(list , sublist) =! -1 you will have a match Collections.indexOfSubList(list , sublist) =! -1你将得到一个匹配

Cheap but ugly solution: 便宜但丑陋的解决方案:

String listStr = list.toString().replace("[", "").replace("]", "");
String sublistStr = sublist.toString().replace("[", "").replace("]", "");

System.out.println(listStr.contains(sublistStr));

Not entirely clear from your question: If the sublist can be contained in the list in order, but with other elements in between, you can use something like this: 从您的问题中不完全清楚:如果子列表可以按顺序包含在列表中,但是其中包含其他元素,则可以使用以下内容:

public static <T> boolean containsInOrder(List<T> list, List<T> sublist) {
    Iterator<T> listIter = list.iterator();
    for (T item : sublist) {
        if (! listIter.hasNext()) {
            // still elements in sublist, but none in list
            return false;
        }
        while (listIter.hasNext() && ! listIter.next().equals(item)) {
            // do nothing, just consume the list until item is found
        }
    }
    // entire sublist found in list
    return true;
}

With list = ["PRP", "VBP", "VBN", "NN", "NNS", "MD", "VB"] , this returns false for sublist = ["MD", "VB", "VBN"] , and true for sublist = ["PRP", "VBN", "VB"] . 使用list = ["PRP", "VBP", "VBN", "NN", "NNS", "MD", "VB"] ,这对于sublist = ["MD", "VB", "VBN"]返回false sublist = ["MD", "VB", "VBN"] ,和truesublist = ["PRP", "VBN", "VB"]

I found it necessary to comment that @JordiCastilla solution is not correct in the sense that it is complete. 我发现有必要评论@JordiCastilla解决方案在完整的意义上是不正确的。 It can be correct if item type has correct equals, because in case of Collections.indexOfSubList you invoke list element type equals . 如果项类型具有正确的等于,则可以是正确的,因为在Collections.indexOfSubList的情况下,您调用列表元素类型equals

/**
 * Compares the specified object with this list for equality.  Returns
 * <tt>true</tt> if and only if the specified object is also a list, both
 * lists have the same size, and all corresponding pairs of elements in
 * the two lists are <i>equal</i>.  (Two elements <tt>e1</tt> and
 * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
 * e1.equals(e2))</tt>.)  In other words, two lists are defined to be
 * equal if they contain the same elements in the same order.  This
 * definition ensures that the equals method works properly across
 * different implementations of the <tt>List</tt> interface.
 *
 * @param o the object to be compared for equality with this list
 * @return <tt>true</tt> if the specified object is equal to this list
 */
boolean equals(Object o);

This however is trivially culture dependent and in case of type String is incorrect. 然而,这在很大程度上依赖于文化,并且在类型String的情况下是不正确的。 Consider for example the case: 考虑一下例如:

String a = "ss";
String b = "ß";                  //german "ss" character
Assert.IsTrue(a.equals(b));      //in java, this will return false even in DE locale

I think reasoning behind it is that character count does not match - in any case it is not correct. 我认为其背后的推理是字符数不匹配 - 无论如何它都是不正确的。 You would think that "at least they got the basics down right" - and you would be wrong : 你会认为“至少他们得到了正确的基础知识” - 你会错的:

"You should be aware that internationalization and localization issues of full Unicode strings are not addressed with [String] methods. For example, when you're comparing two strings to determine which is 'greater', characters in strings are compared numerically by their Unicode values, not by their localized notion of order." “你应该知道,使用[String]方法不能解决完整Unicode字符串的国际化和本地化问题。例如,当您比较两个字符串以确定哪个是'更大'时,字符串中的字符将通过Unicode进行数字比较价值观,而不是他们本地化的秩序概念。“

In Unicode however same string can have multiple representations and they would not equate. 但是在Unicode中,同一个字符串可以有多个表示形式,它们不等同。 Type String is an example but you could have any custom data type. Type String是一个示例,但您可以拥有任何自定义数据类型。

Long story short : make sure your item type equals has the correct implementation. 长话短说 :确保你的项目类型等于正确的实现。


Another example how this can trivially be wrong is following: 另一个例子,如何解决这个问题的方法如下:

List arrlistsrc = new ArrayList();
List arrlisttarget = new ArrayList();

arrlistsrc.add("A");
arrlistsrc.add("B");
arrlistsrc.add("C");

arrlisttarget.add("A");
arrlisttarget.add("C");

int index = Collections.indexOfSubList(arrlistsrc, arrlisttarget); // this will be -1

First list contains second one and they have the same order, but in between elements target elements source contains other elements. 第一个列表包含第二个列表,它们具有相同的顺序,但在元素之间,目标元素源包含其他元素。

To find that you can use something in the lines : 要找到你可以在行中使用的东西:

boolean ContainsOrderedSublist<T>(IList<T> arrlistsrc, IList<T> arrlisttarget){
    int slider = 0;
    for (String val: arrlisttarget ) {
        slider = arrlistsrc.indexOf(val, slider);// or use culture independent version
        if(slider < 0) break;
    }
    return slider < 0;    
}

(NB : code examples not tested and written from head) (注意:代码示例未经过测试和编写)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM