[英]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"]
,和true
为sublist = ["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.