我有以下数据结构:
基本上我在这里有一个列表,其中包含其他列表(它们的大小可以是任意的,在我的情况下,所有4个列表的大小都是2)。我必须分组,以便具有相同元素的列表进入一个列表(可能不是最好的配方,但我不能更好地制定它)。在我的情况下,结果应如下:
[72, 83, 127]
和[110, 119]
。
例如,如果第三个子列表包含元素[83, 127, 55, 22]
,则结果应如下所示:[72, 83, 127, 55, 22]
和[110, 119]
。 (所以我必须包括所有子列表元素。)
我如何在Java或Groovy中做这样的事情?
答案 0 :(得分:1)
由于您必须处理整个列表,因此一个不错的选择是利用groovy collection的inject方法(添加println
来显示步骤):
def values = [[72, 83], [72, 127], [83, 127], [110, 119]]
def result = values.inject([], { res, value ->
println "res = $res | value = $value"
def found = res.find {
if (it.intersect(value)) {
it.addAll(value - it)
true
}
}
if (!found) {
res << value
}
res
})
println result
assert [[72, 83, 127], [110, 119]] == result
那样:
res = [] | value = [72, 83]
res = [[72, 83]] | value = [72, 127]
res = [[72, 83, 127]] | value = [83, 127]
res = [[72, 83, 127]] | value = [110, 119]
[[72, 83, 127], [110, 119]]
编辑:上述解决方案在某些情况下效果不佳,即
def values = [[72, 83], [72, 127], [83, 127], [110, 119], [47, 56], [56, 72]]
产量
[[72, 83, 127, 56], [110, 119], [47, 56]]
如果列表被排序,它会产生(我认为这是正确的解决方案)
[[47, 56, 72, 83, 127], [110, 119]]
编辑(2):解决上一个问题的更好解决方案(即列表共享元素包含多个结果列表):
def values = [[72, 83], [72, 127], [83, 127], [110, 119], [120, 121], [121, 127]]
def result = values.inject([], { res, value ->
println "res = $res | value = $value"
def found = res.findAll { it.intersect(value) }
println " -> found = $found"
if (!found) {
res << value
} else {
res.removeAll(found)
def merged = found.collect({ it + value as Set }).flatten() as Set
println " -> merged = $merged"
res << merged
}
println " => res = $res"
res
})
答案 1 :(得分:0)
这是使用maps的java实现。首先,我们将ArrayList转换为映射,即key = integerInList + value = NoOfOccurrence。然后我们只搜索地图中的每个元素,如果元素有多于1个出现,那么我们只需添加到相应的组(Set)。
public static void find() {
//Input Data
ArrayList<List<Integer>> list1 = new ArrayList<>();
list1.add(Arrays.<Integer>asList(72, 83));
list1.add(Arrays.<Integer>asList(72, 127));
list1.add(Arrays.<Integer>asList(83, 127));
list1.add(Arrays.<Integer>asList(110, 119));
Map<Integer, Integer> map = new HashMap<>();
//Convert Input Data to Map
for (List<Integer> integers : list1) {
for (Integer integer : integers) {
int integer1=1;
if (map.containsKey(integer)) {
integer1 += map.get(integer);
}
map.put(integer, integer1);
}
}
Set<Integer> group1 = new HashSet<>();
Set<Integer> group2 = new HashSet<>();
//find and build groups
for (List<Integer> integers : list1) {
boolean found = false;
for (Integer integer : integers) {
if (map.containsKey(integer)) {
if (map.get(integer) > 1) {
found = true;
break;
}
}
}
if (found) {
group1.addAll(integers);
} else {
group2.addAll(integers);
}
}
System.out.println("group1 = " + group1);
System.out.println("group2 = " + group2);
}