【问题标题】:How to check if a list contains a sublist in a given order in Java如何检查列表是否包含Java中给定顺序的子列表
【发布时间】:2015-09-30 11:31:22
【问题描述】:

我在 groovy how to check if a list contains a sublist - stackoverflow 中阅读。

如果有一种方法可以检查列表是否包含子列表,但按给定的顺序,我很感兴趣。例如,这段代码将给出 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));

但我想找回 false

【问题讨论】:

  • 迭代。没有直接的方法。
  • @ergonaut 请检查我的答案... java 有一些不为人知的内置函数
  • 可以穿插其他元素吗? [PRP, NNS] 会按顺序包含吗?
  • @JordiCastilla 谢谢,我从来不知道!

标签: java list collections


【解决方案1】:

您可以使用方法Collections.indexOfSubList

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

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

简短:
如果Collections.indexOfSubList(list , sublist) =! -1你会有匹配的

【讨论】:

  • 谢谢,这正是我需要的。
【解决方案2】:

便宜但丑陋的解决方案:

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

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

【讨论】:

  • 检查我的解决方案,Collections 是你的朋友 / mira't la meva sol.lució,Collections es el teu amic ;)
  • 我同意 100%,我每天都使用 Apache Commons :-)
【解决方案3】:

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

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"],这将返回false 用于sublist = ["MD", "VB", "VBN"],并返回true 用于sublist = ["PRP", "VBN", "VB"]

【讨论】:

  • 我不允许中间有其他元素。 @JordiCastilla 提供了我正在寻找的解决方案。
  • 如果子列表中的最后一个元素不在列表中,这是不正确的。它可以返回true。最简单的例子是当子列表包含一个不在列表中的值时。函数返回真。应该是假的。
【解决方案4】:

我发现有必要评论 @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 a = "ss";
String b = "ß";                  //german "ss" character
Assert.IsTrue(a.equals(b));      //in java, this will return false even in DE locale

我认为其背后的原因是字符数不匹配 - 在任何情况下都是不正确的。你会认为“至少他们的基础知识是正确的”——你错了:

“您应该意识到国际化和本地化问题 完整的 Unicode 字符串不使用 [String] 方法处理。为了 例如,当您比较两个字符串以确定哪个是 'greater',字符串中的字符通过它们的数字进行比较 Unicode 值,而不是它们的本地化顺序概念。”

然而,在 Unicode 中,相同的字符串可以有 多个 表示,并且它们不会等同。类型 String 是一个示例,但您可以使用任何自定义数据类型。

长话短说:确保您的项目类型 equals 具有正确的实现。


这可能是微不足道的错误的另一个例子如下:

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

(注意:代码示例未从头测试和编写)

【讨论】:

  • 为什么ss 应该被认为等于ßß 不仅仅是一个印刷连字,而是一个不同的字母。 “in Massen”与“in Maßen”的发音含义完全不同。另外,您为什么认为这与 OP 的情况有关?关于你的“另一个例子”:这也是我理解这个问题的方式,但显然它是错误的......
  • 在第二种情况下,我想指出 { A, B, C } 包含有序列表 { A, C },但元素不是必然的。在第一种情况下,我想指出平等具有文化成分,而大多数人对此视而不见。你可以心血来潮想出一个更好的例子,我就其他没有。除了 C#.Net 中的对比 "Strasse".Equals("Straße", StringComparison.InvariantCulture);" 将返回 true (与 CompareTo 相同)。
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多