繁体   English   中英

如何基于第一个元素合并多个数组列表?

[英]How to merge several list of arrays based on first element?

我有几个字符串数组列表。 我想根据每个数组的第一个元素将此列表合并为一个列表。

基本上,我想合并这两个列表

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"});

在这个

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

还有一些事情:

  • 列表顺序无关紧要
  • 数组顺序很重要,所以如果值不存在,我必须添加填充

有人知道一种有效的方法吗?

我目前的做法

我目前的方法使用 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]

基本上,您需要做的是检查list2是否存在所需的密钥。 如果是,只需合并数组。 但是,如果 key 不存在于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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM