繁体   English   中英

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

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

我在groovy中读到如何检查列表是否包含子列表 - stackoverflow

我感兴趣的是,有一种方法可以检查列表是否包含子列表,但是按给定的顺序。 例如,这段代码将给出真实的

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

但是,我想回来。

您可以使用方法Collections.indexOfSubList

返回指定源列表中指定目标列表第一次出现的起始位置,如果不存在,则返回-1 更正式地,返回最低索引i,使得source.subList(i, i+target.size()).equals(target) ,或者如果没有这样的索引则返回-1 (如果target.size() > source.size()则返回-1 。)

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

短:
如果Collections.indexOfSubList(list , sublist) =! -1 Collections.indexOfSubList(list , sublist) =! -1你将得到一个匹配

便宜但丑陋的解决方案:

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

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

从您的问题中不完全清楚:如果子列表可以按顺序包含在列表中,但是其中包含其他元素,则可以使用以下内容:

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

使用list = ["PRP", "VBP", "VBN", "NN", "NNS", "MD", "VB"] ,这对于sublist = ["MD", "VB", "VBN"]返回false sublist = ["MD", "VB", "VBN"] ,和truesublist = ["PRP", "VBN", "VB"]

我发现有必要评论@JordiCastilla解决方案在完整的意义上是不正确的。 如果项类型具有正确的等于,则可以是正确的,因为在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);

然而,这在很大程度上依赖于文化,并且在类型String的情况下是不正确的。 考虑一下例如:

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

我认为其背后的推理是字符数不匹配 - 无论如何它都是不正确的。 你会认为“至少他们得到了正确的基础知识” - 你会错的:

“你应该知道,使用[String]方法不能解决完整Unicode字符串的国际化和本地化问题。例如,当您比较两个字符串以确定哪个是'更大'时,字符串中的字符将通过Unicode进行数字比较价值观,而不是他们本地化的秩序概念。“

但是在Unicode中,同一个字符串可以有多个表示形式,它们不等同。 Type String是一个示例,但您可以拥有任何自定义数据类型。

长话短说 :确保你的项目类型等于正确的实现。


另一个例子,如何解决这个问题的方法如下:

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

第一个列表包含第二个列表,它们具有相同的顺序,但在元素之间,目标元素源包含其他元素。

要找到你可以在行中使用的东西:

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

(注意:代码示例未经过测试和编写)

暂无
暂无

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

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