问题如下。有多个行具有非唯一标识符:
id value
0: {1,2,3}
0: {1,2,2}
1: {1,2,3}
2: {1,2,3}
2: {1,1,3}
我有一个函数equals
,它可以比较彼此之间的多行。我需要编写一个代码来选择行作为函数equals
的输入。选择的行必须具有唯一的ID,但我应该检查所有可能的唯一ID组合。例如,如果有5行带有id:0,0,1,2,3,那么我应该检查以下两种id组合:0,1,2,3和0,1,2,3,因为0 apears两次。当然,这两种组合中的每一种都将由id = 0的唯一行组成。
我的代码段如下:
public class Test {
public static void main(String[] args) {
ArrayList<Row> allRows = new ArrayList<Row>();
allRows.add(new Row(0,new int[]{1,2,3}));
allRows.add(new Row(0,new int[]{1,2,2}));
allRows.add(new Row(1,new int[]{1,2,3}));
allRows.add(new Row(2,new int[]{1,2,3}));
allRows.add(new Row(2,new int[]{1,1,3}));
boolean answer = hasEqualUniqueRows(allRows);
}
private boolean hasEqualUniqueRows(ArrayList<Row> allTokens) {
for (int i=0; i<allTokens.size(); i++) {
ArrayList<Integer[]> rows = new ArrayList<Integer[]>();
rows = findUniqueRows(i,allTokens);
boolean answer = equalsExceptForNulls(rows);
if (answer) return true;
}
return false;
}
// Compare rows for similarities
public static <T> boolean equalsExceptForNulls(ArrayList<T[]> ts) {
for (int i=0; i<ts.size(); i++) {
for (int j=0; j<ts.size(); j++) {
if (i != j) {
boolean answer = equals(ts.get(i),ts.get(j));
if (!answer) return false;
}
}
}
return true;
}
public static <T> boolean equals(T[] ts1, T[] ts2) {
if (ts1.length != ts2.length) return false;
for(int i = 0; i < ts1.length; i++) {
T t1 = ts1[i], t2 = ts2[i];
if (t1 != null && t2 != null && !t1.equals(t2))
return false;
}
return true;
}
class Row {
private String key;
private Integer[] values;
public Row(String k,Integer[] v) {
this.key = k;
this.values = v;
}
public String getKey() {
return this.key;
}
public Integer[] getValues() {
return this.values;
}
}
}
由于具有唯一ID的行数是先验未知的,我不知道如何解决这个问题。有什么建议?感谢。
编辑#1
我更新了代码。现在它更完整了。但它缺乏函数findUniqueRows
的实现。此函数应从ArrayList中选择具有唯一键(ids)的行。有人可以帮我开发这个功能吗?感谢。
答案 0 :(得分:1)
假设目标是找到没有重复的每个组合,您可以使用以下方法执行此操作。查找重复项的测试只是为了确认它首先不会生成任何重复项。
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String... args) {
Bag<Integer> b = new Bag<>();
b.countFor(1, 2);
b.countFor(2, 1);
b.countFor(3, 3);
Set<String> set = new LinkedHashSet<>();
for (List<Integer> list : b.combinations()) {
System.out.println(list);
String s = list.toString();
if (!set.add(s))
System.err.println("Duplicate entry " + s);
}
}
}
class Bag<E> {
final Map<E, AtomicInteger> countMap = new LinkedHashMap<>();
void countFor(E e, int n) {
countMap.put(e, new AtomicInteger(n));
}
void decrement(E e) {
AtomicInteger ai = countMap.get(e);
if (ai.decrementAndGet() < 1)
countMap.remove(e);
}
void increment(E e) {
AtomicInteger ai = countMap.get(e);
if (ai == null)
countMap.put(e, new AtomicInteger(1));
else
ai.incrementAndGet();
}
List<List<E>> combinations() {
List<List<E>> ret = new ArrayList<>();
List<E> current = new ArrayList<>();
combinations0(ret, current);
return ret;
}
private void combinations0(List<List<E>> ret, List<E> current) {
if (countMap.isEmpty()) {
ret.add(new ArrayList<E>(current));
return;
}
int position = current.size();
current.add(null);
List<E> es = new ArrayList<>(countMap.keySet());
if (es.get(0) instanceof Comparable)
Collections.sort((List) es);
for (E e : es) {
current.set(position, e);
decrement(e);
combinations0(ret, current);
increment(e);
}
current.remove(position);
}
}