如何使用另一列作为条件来连接矩阵中的列的行

时间:2016-08-23 18:37:04

标签: java arrays

设置我有以下数组:

String[ ] array = new String {
    { a2,  a4,  a5,  a1,  a3 },
    {5.0, 2.0, 5.0, 2.0, 2.0 }
};

安排为5X2矩阵:

(a2; 2.0)

(a4; 2.0)

(a5; 2.0)

(a1; 5.0)

(a3; 5.0)

我希望使用第二列中的值作为条件连接第一列的行,生成以下2X2矩阵:

(" a2,a4,a5&#34 ;; 2.0)

(" a1,a3&#34 ;; 5.0)

谢谢!

4 个答案:

答案 0 :(得分:3)

我们需要做的第一件事是将数组类型更改为Object[][],以便它可以包含字符串和数字:

Object[][] array = {
    { "a2",  "a4",  "a5",  "a1",  "a3" },
    { 5.0, 2.0, 5.0, 2.0, 2.0 }
};

现在我们使用流来生成按其对应的数值分组的串联字符串值的映射,然后我们将映射条目流式化为2列矩阵:

Object[][] grouped = IntStream.range(0, array[0].length) // this will create a stream containing as many natural numbers, starting from 0, that the array has elements
        .boxed() // this will make it a stream of Integers instead of ints
        .collect(groupingBy(i -> array[1][i], mapping(i -> array[0][i].toString(), joining(", ")))) // here, we make a Map out of the stream by grouping by the i'th element of the second column in the matrix and taking as the value the respective element from the first column, then joining the resulting list of strings in the map's value with a ", " separator
        .entrySet() // now we take the entry set of the map
        .stream() // we stream it
        .map(e -> new Object[] {e.getValue(), e.getKey()}) // and we transform each entry in the map into a matrix row
        .toArray(Object[][]::new); // finally, we transform the stream of rows into a matrix (array of rows)

以上内容依赖于java.util.stream.Collectors.*的静态导入。

这很容易适用于使用纯字符串矩阵,如果这就是你所追求的。

答案 1 :(得分:0)

不知道你的数字是如何存储的,但假设它们是BigDecimals(出于散列的原因),请使用Map<BigDecimal, StringBuilder>来聚合项目。因此,如果您的地图已经contains()给定的小数点append()到相应的StringBuilder,如果没有,则创建一个新的小数点。此外,对于迭代矩阵,使用带有共享索引的for循环来并行迭代这两个数组。

答案 2 :(得分:0)

我不认为这是最好/最安全的代码(我在数组上做了一些假设),但它会让你开始。

首先,修复你的数组:

String[][] array = new String[][]{{"a2","a4","a5","a1","a3"},
                                 {"5.0", "2.0", "5.0", "2.0", "2.0"}};

现在,

Map<String, StringBuilder> map = new HashMap<>();
for (int i = 0; i < array[0].length; i ++) {
    map.putIfAbsent(array[1][i], new StringBuilder());
    map.get(array[1][i]).append(array[0][i]).append(" "); // Build the collected "a1, a3"  grouping by the second value;
}

String[][] result = new String[2][map.size()];
int j = 0;
for(Map.Entry<String, StringBuilder> entry : map) {
    result[j][0] = entry.getValue().toString();
    result[j][1] = entry.getKey();
}

我想我可以用流来做这件事,但我必须考虑一下。

答案 3 :(得分:0)

这是我在不使用流的情况下解决问题的方法。但是,和其他人一样,我不确定使用哪种数据类型。

private static final int SIZE_KEY_PLUS_CONCATENATION = 2;
private static final int INDEX_OF_KEY = 1;
private static final int INDEX_OF_VALUE = 0;
private static final String SEPARATOR = ", ";

private static final int RESULT_KEY = 0;
private static final int RESULT_VALUE = 1;
private static final String RESULT_SEPARATOR = " : ";

public static void main(String[] args) {
    String[][] matrix = new String[][]{
            {"a2", "5.0"},
            {"a4", "2.0"},
            {"a5", "5.0"},
            {"a1", "2.0"},
            {"a3", "2.0"},
    };

    String[][] result = getConcatenatedMatrix(matrix);
    for(String[] row : result) {
        System.out.println(row[RESULT_KEY] + RESULT_SEPARATOR + row[RESULT_VALUE]);
    }
}

private static String[][] getConcatenatedMatrix(String[][] inputMatrix) {
    Map<String, String> map = generateMapWithConcatenatedValues(inputMatrix);
    return convertMapToMatrix(map);

}

private static Map<String, String> generateMapWithConcatenatedValues(String[][] inputMatrix) {
    Map<String, String> map = new HashMap<>();
    for(String[] row : inputMatrix) {
        String key = row[INDEX_OF_KEY];
        String value = row[INDEX_OF_VALUE];
        doConcatenation(key, value, map);
    }

    return map;
}

private static void doConcatenation(String key, String value, Map<String, String> map) {
    if(map.containsKey(key)) {
        map.put(key, map.get(key) + SEPARATOR + value);
    } else {
        map.put(key, value);
    }
}

private static String[][] convertMapToMatrix(Map<String, String> mapToConvert) {
    int keyCount = mapToConvert.size();
    String[][] result = new String[keyCount][SIZE_KEY_PLUS_CONCATENATION];
    Set<String> keys = mapToConvert.keySet();
    int currentKey = 0;
    for(String key : keys) {
        result[currentKey][RESULT_KEY] = key;
        result[currentKey][RESULT_VALUE] = mapToConvert.get(key);
        currentKey++;
    }

    return result;
}