2015-04-04 55 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); 
}