2015-11-13 60 views
1

我有幾個字符串數組列表。我想根據每個數組的第一個元素將這些列表合併到一個列表中。如何合併幾個基於第一個元素的數組列表?

基本上,我想在這一個

[key4,a,a,a,null,null] 
[key3,null,null,null,c,c] 
[key2,a,a,a,b,b] 
[key1,a,a,a,b,b] 

一些更多的東西合併這兩個列表

ArrayList<String[]> list1 = new ArrayList<String[]>(); 
list1.add(new String[]{"key1","a","a","a"}); 
list1.add(new String[]{"key2","a","a","a"}); 
list1.add(new String[]{"key4","a","a","a"}); 

ArrayList<String[]> list2 = new ArrayList<String[]>(); 
list2.add(new String[]{"key1","b","b"}); 
list2.add(new String[]{"key2","b","b"}); 
list2.add(new String[]{"key3","c","c"}); 

  • 列表順序並不重要
  • 陣列訂單是重要,所以我必須添加填充如果值不存在

有人知道有效的方法來做到這一點嗎?

我目前的做法

我目前的做法使用一個HashMap來存儲密鑰(數組的第一個元素)

HashMap<String, String[]> results = new HashMap<String, String[]>(); 
process(list1); 
process(list2); 

void process(ArrayList<String[]> list) { 
    for(String[]s : list) { 
     if(!results.containsKey(s[0])) { 
      results.put(s[0], Arrays.copyOfRange(s, 1, s.length)); 
     } else { 
      String[] current = results.get(s[0]); 
      results.put(s[0], concat(current, Arrays.copyOfRange(s, 1, s.length))); 
     } 
    } 
} 

這給我的輸出中(不正確的,因爲沒有「填充」)

key4 [a, a, a] 
key3 [c, c] 
key2 [a, a, a, b, b] 
key1 [a, a, a, b, b] 
+0

是否所有的數組總是有表1和2中相同的長度? – user1438038

+0

在同一列表中,數組的長度相同。但是list1和list2中的數組可以有不同的大小。 – ThomasThiebaud

+0

並且列表2還可以包含一個不是*列表1中存在的鍵嗎? – user1438038

回答

1

基本上,你需要做的是檢查list2如果所需的密鑰存在。如果是這樣,只需合併數組。但是,如果密鑰在list2中不存在,則必須添加填充數組。這可以通過返回一個具有所需長度的新數組來完成。

看一看下面我的代碼:

public void mergeArrays() { 

    ArrayList<String[]> list1 = new ArrayList<String[]>(); 
    list1.add(new String[] { "key1", "a", "a", "a" }); 
    list1.add(new String[] { "key2", "a", "a", "a" }); 
    list1.add(new String[] { "key4", "a", "a", "a" }); 

    ArrayList<String[]> list2 = new ArrayList<String[]>(); 
    list2.add(new String[] { "key1", "b", "b" }); 
    list2.add(new String[] { "key2", "b", "b" }); 
    list2.add(new String[] { "key3", "c", "c" }); 

    ArrayList<String[]> result = new ArrayList<String[]>(); 

    // Merge list1 to list2 
    for (String[] array1: list1) { 
    // Find key from list1 in list2 
    int index = this.findIndex(array1[0], list2); 

    // Key was found, merge arrays 
    if (index > -1) { 
     result.add(this.concat(array1, list2.get(index))); 
    } 
    // Key was not found, use padding 
    else { 
     // Padding second array with null values 
     result.add(this.concat(array1, this.padding(list2.get(0).length, null))); 
    } 
    } 

    // Merge list2 to list1 
    for (String[] array2: list2) { 
    // Find key from list2 in list1 
    int index = this.findIndex(array2[0], list1); 

    // Key was not found, use padding 
    if (index == -1) { 
     // Padding first array with null values 
     String[] temp = this.concat(this.padding(list1.get(0).length, null), array2); 
     temp[0] = array2[0]; // Set key 
     result.add(temp); 
    } 
    } 

    // Debug output 
    for (String[] array: result) { 
    for (int i = 0; i < array.length; ++i) { 
     System.out.print(array[i] + " "); 
    } 
    System.out.println(""); 
    } 
} 

// Return array with padding 
private String[] padding(final int size, final String padding) { 
    String[] result = new String[size]; 
    Arrays.fill(result, padding); 

    return result; 
} 

// Find needle in haystack and return index 
private int findIndex(final String needle, final ArrayList<String[]> haystack) { 
    for (int i = 0; i < haystack.size(); ++i) { 
    if (haystack.get(i)[0].equals(needle)) { 
     return i; 
    } 
    } 

    return -1; 
} 

// Merge two arrays, omit first element of second array 
private String[] concat(String[] arrayOne, String[] arrayTwo) { 
    int arrayOneLength = arrayOne.length; 
    int arrayTwoLength = arrayTwo.length; 

    String[] result = new String[arrayOneLength + arrayTwoLength - 1]; 
    System.arraycopy(arrayOne, 0, result, 0, arrayOneLength); 
    System.arraycopy(arrayTwo, 1, result, arrayOneLength, arrayTwoLength - 1); // Skip key in second array 

    return result; 
} 

輸出:

key1 a a a b b 
key2 a a a b b 
key4 a a a null null 
key3 null null null c c 
+0

它是否適用於2個以上的列表? – ThomasThiebaud

+0

你可以改變''mergeArrays()'',例如返回結果並提供兩個參數傳入''list1''和''list2''。然後,您將可以使用不同的參數多次調用該方法,併合並兩個以上的列表。 – user1438038

+1

我做到了,它工作正常。我只需要像'mergeArrays(list1,mergeArrays(list2,list3))'這樣將鏈接調用到'mergeArrays'。感謝您的回答 – ThomasThiebaud

相關問題