我有List<List<String>>
样本数据,如:
("T1#R1", "T1#R1", "T1#R3", "T1#R4")
("T1#R1", "T1#R1", "T1#R3", "T1#R5")
("T1#R1", "T1#R1", "T1#R6", "T1#R4")
("T1#R1", "T1#R1", "T1#R6", "T1#R5")
我需要声明,上述样本中存在List<String>
,但未考虑订单。
例如,以下列表("T1#R1", "T1#R1", "T1#R4", "T1#R3")
应被视为存在于List<List<String>>
中,因为它将包含与第一个列表相同的项目,但顺序不同。
另一方面,("T1#R1", "T1#R3", "T1#R4", "T1#R3")
不应被视为列表中存在,因为它具有相同的项目,但具有不同的计数。
我知道我可以通过编程方式执行此操作,但是如果有Matcher
例如可以提供帮助,则会徘徊。
我已经看到过像:
assertThat(myList, containsInAnyOrder(anotherList.toArray())
但是这只会将一个列表与另一个列表进行比较,而不是列表列表中的列表。
PS:我使用的是Java6,hamcrest-core-1.3,testng-5.14.1
答案 0 :(得分:3)
我不知道任何匹配器可以做你想做的事情,所以我担心你必须编程。
我只是对目标列表进行排序,然后我会迭代子列表,直到找到匹配项:
List<String> target = new ArrayList<>(anotherList);
target.sort();
boolean result = myList.stream()
.anyMatch(sublist -> equalsInAnyOrder(sublist, target));
方法equalsInAnyOrder
如下:
public <T> boolean equalsInAnyOrder(List<T> sublist, List<T> target) {
List<String> copy = new ArrayList<>(sublist);
copy.sort();
return copy.equals(target);
}
这会对每个子列表进行排序,并将其与目标排序列表进行比较,因此它不是性能方面的,但至少它是简单且简洁的代码。
根据OP的目标编辑Java 6:
逻辑与Java 8版本完全相同。首先对目标列表进行排序,然后比较每个子列表,直到找到匹配项:
List<String> target = new ArrayList<>(anotherList);
Collections.sort(target);
stream()
anyMatch
已成为while
循环:
boolean match = false;
Iterator<List<String>> it = myList.iterator();
while (it.hasNext() && !match) {
List<String> sublist = it.next();
match = equalsInAnyOrder(sublist, target);
}
现在方法equalsInAnyOrder
看起来像这样:
public <T> boolean equalsInAnyOrder(List<T> sublist, List<T> target) {
List<String> copy = new ArrayList<>(sublist);
Collections.sort(copy);
return copy.equals(target);
}
答案 1 :(得分:2)
我没有获得单行解决方案,但我的测试通过了。
我遍历列表列表,将每个列表包装到地图(条目是键,计算值)以及要检查的列表。现在我可以检查是否平等:
public void listOfLists() throws Exception {
List<List<String>> myList = Arrays.asList(
Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R4"),
Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R5"),
Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R4"),
Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R5"));
List<String> easy = Arrays.asList("T1#R1", "T1#R1", "T1#R4", "T1#R3");
List<String> duplicate = Arrays.asList("T1#R1", "T1#R5", "T1#R1", "T1#R6");
List<String> noMatch = Arrays.asList("T1#R1", "T1#R5", "T1#R6");
Map<String, Integer> easyCount = countEntries(easy);
Map<String, Integer> duplicateCount = countEntries(duplicate);
Map<String, Integer> noCount = countEntries(noMatch);
for (List<String> l : myList) {
Map<String, Integer> countedEntries = countEntries(l);
if (countedEntries.equals(easyCount)) {
System.out.println("easy matches");
}
if (countedEntries.equals(duplicateCount)) {
System.out.println("duplicate matches");
}
if (countedEntries.equals(noCount)) {
System.out.println("Damn!");
}
}
}
private Map<String, Integer> countEntries(List<String> original) {
return original.stream()
.collect(Collectors.toMap(Function.identity(), s -> 1, Integer::sum));
}
打印
easy matches
duplicate matches
答案 2 :(得分:0)
我不知道任何Matcher这样做,你是否关心重复? (你的字符串中会有重复的值吗?)
我会那样做:
private boolean containsInAnyOrder(List<List<String>> container, List<String> list)
{
for (List<String> list1 : container)
{
if(list.size()==list1.size())
{
if(list1.containsAll(list))
{
return true;
}
}
}
return false;
}
仅当您不关心重复元素并且计数时才会起作用。
("T1#R1", "T1#R1", "T1#R1", "T1#R2")
("T1#R1", "T1#R2", "T1#R2", "T1#R1")
例如,将返回true。你有重复吗? (对于Set解决方案,它也不会出于同样的原因)
如果有重复项,您需要计算每个项目:
private boolean containsInAnyOrder(List<List<String>> container, List<String> list)
{
for (List<String> list1 : container)
{
if(list.size()==list1.size())
{
boolean found = true;
for(String string : list)
{
if (list.stream().filter(pS -> pS.equals(string)).count() != list1.stream().filter(pS -> pS.equals(string)).count())
{
found = false;
}
}
if(found)
{
return true;
}
}
}
return false;
}
请注意,它没有经过优化,内部for循环可以在不匹配的情况下停止。