断言 List<List<String>> 包含没有顺序的 List<String>
Assert List<List<String>> contains List<String> with no order
我有一个 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
我不知道有哪个 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")
例如, 会 return 为真。你有重复的吗? (对于 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 循环可能会在之前停止。
我不知道有任何匹配器可以满足您的要求,所以恐怕您必须对其进行编程。
我会简单地对目标列表进行排序,然后迭代子列表直到找到匹配项:
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:
逻辑和Java8版本完全一样。首先对目标列表进行排序,然后比较每个子列表,直到找到匹配项:
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);
}
我没有得到单行解决方案,但我的测试通过了。
我遍历列表列表,将每个列表包装到一个映射(条目是键,计算值)以及要检查的列表。现在我可以检查是否相等:
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
我有一个 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
我不知道有哪个 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")
例如,会 return 为真。你有重复的吗? (对于 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 循环可能会在之前停止。
我不知道有任何匹配器可以满足您的要求,所以恐怕您必须对其进行编程。
我会简单地对目标列表进行排序,然后迭代子列表直到找到匹配项:
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:
逻辑和Java8版本完全一样。首先对目标列表进行排序,然后比较每个子列表,直到找到匹配项:
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);
}
我没有得到单行解决方案,但我的测试通过了。
我遍历列表列表,将每个列表包装到一个映射(条目是键,计算值)以及要检查的列表。现在我可以检查是否相等:
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