给定以下数据类型Testcase(XQuery,Testpath,FirstInputFile,SecondInputFile,Expected)
如何正确删除重复项.
重复的定义:
如果FirstInputFile已经在列表中作为SecondInputFile反之亦然.
这是Testdata
tcs.add(new HeaderAndBodyTestcase("XQ 1", "/1", "FAIL", "FAIL2", "FAILED"));
tcs.add(new HeaderAndBodyTestcase("XQ 1", "/1", "FAIL2", "FAIL", "FAILED"));
tcs.add(new HeaderAndBodyTestcase("XQ 2", "/2", "FAIL4", "FAIL3", "FAILED2"));
tcs.add(new HeaderAndBodyTestcase("XQ 2", "/2", "FAIL3", "FAIL4", "FAILED2"));
这是功能
protected void deleteExistingDuplicatesInArrayList(final ArrayList<HeaderAndBodyTestcase> list) {
for (int idx = 0; idx < list.size() - 1; idx++) {
if (list.get(idx).firstInputFile.equals(list.get(idx).secondInputFile)
|| (list.get(idx + 1).firstInputFile.equals(list.get(idx).firstInputFile)
&& list.get(idx).secondInputFile.equals(list.get(idx + 1).secondInputFile)
|| (list.get(idx).firstInputFile.equals(list.get(idx + 1).secondInputFile)
&& list.get(idx).secondInputFile.equals(list.get(idx + 1).firstInputFile)))) {
list.remove(idx);
}
}
}
这个解决方案已经有效,但看起来很糟糕,那么有更好的解决方案吗?
解决方法:
鉴于你相当特殊的“平等”约束,我认为最好的方法是维护两套已经看过的第一和第二个输入文件和一个循环:
Set<String> first = new HashSet<>();
Set<String> second = new HashSet<>();
for (HeaderAndBodyTestcase tc : tcs) {
if (! first.contains(tc.getSecondInputFile()) &&
! second.contains(tc.getFirstInputFile())) {
first.add(tc.getFirstInputFile());
second.add(tc.getSecondInputFile());
System.out.println(tc); // or add to result list
}
}
如果“相等”元素在原始列表中不会彼此相继出现,这也将起作用.
另请注意,在迭代相同列表时从列表中删除元素,有时会工作,通常会产生意外结果.更好地创建一个新的过滤列表,或者如果必须删除,从该列表创建一个Iterator并使用它的remove方法.
仔细检查(是的,我花了很长时间才能理解你的代码),你当前工作代码中的条件实际上与我从你的问题中理解的条件大不相同,即:
>如果第一个和第二个相同,则删除元素(实际上从未检查过列表中的最后一个元素)
>如果first与最后一个相同,则删除元素,第二个与最后一个相同
>如果第一个与最后一秒相同则删除,反之亦然
>只考虑连续元素(来自评论)
鉴于这些约束,不需要这些集合,并且考虑到两个元素必须匹配(“直线”或“交叉”),也不会正常工作.相反,您可以按原样使用相当多的代码,但我仍然会使用Iterator并跟踪最后一个元素,并且还会拆分不同的检查以使整个代码更容易理解.
HeaderAndBodyTestcase last = null;
for (Iterator<HeaderAndBodyTestcase> iter = list.iterator(); iter.hasNext();) {
HeaderAndBodyTestcase curr = iter.next();
if (curr.firstInputFile.equals(curr.secondInputFile)) {
iter.remove();
}
if (last != null) {
boolean bothEqual = curr.firstInputFile.equals(last.firstInputFile)
&& curr.secondInputFile.equals(last.secondInputFile);
boolean crossedEqual = curr.secondInputFile.equals(last.firstInputFile)
&& curr.firstInputFile.equals(last.secondInputFile);
if (bothEqual || crossedEqual) {
iter.remove();
}
}
last = curr;
}