2015-04-04 33 views
1

我有以下数据结构:组元素

enter image description here

基本上我在这里有一个列表,包含其他列表(其大小可以是任意的,在我的情况下,所有4只列出有大小2 )。我必须进行分组,以便将具有相同元素的列表放入一个列表(可能不是最佳配方,但我无法更好地制定它)。在我的情况下,结果应该如下: [72, 83, 127][110, 119]

如果例如三分之二子列表包含元素[83, 127, 55, 22],则结果应该如下:[72, 83, 127, 55, 22][110, 119]。 (所以我必须包含所有子列表元素)。

如何在Java或Groovy中执行此类操作?

+1

我完全困惑于你想如何决定输入中的一个元素应该进入哪个输出列表。 – 2015-04-04 11:19:43

+0

好吧,子列表0包含72和83.子列表1包含72和127.由于两者都包含72,所以我们合并它们。子列表2包含83和127.由于子列表1还包含83(或第二个包含128),所以我们也合并了子列表1和3. – Bob 2015-04-04 11:21:45

+0

所以......你是说你想合并列表如果交叉点他们之间是不是空的? – 2015-04-04 11:22:42

回答

1

既然你要处理整个列表,一个很好的选择是利用常规收集的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]] 

EDIT(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 
}) 
+0

你是什么意思,“如果列表排序”? – Bob 2015-04-04 17:58:08

+0

[[47,56],[56,72],[72,83],[72,127],[83,127],[110,119]] – jalopaba 2015-04-04 18:07:52

+0

好的,我将使用.sort()方法。 – Bob 2015-04-04 18:08:24

0

这里是使用地图的java实现。首先我们将ArrayList转换为映射,即key = integerInList + value = NoOfOccurrence。然后,我们只搜索地图中的每个元素,如果该元素具有多于一个的发生,那么我们只需添加到相应的组(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); 
}