如何从多值映射中删除“垂直重复”值?

时间:2018-03-03 19:01:18

标签: java dictionary data-structures

不幸的是,我正在使用Java中的一些不太美味的数据结构,我的任务是在多值映射(Map<Enum, List<String>>)中删除我称之为“垂直重复”的内容。其中所有值(List<String>)的大小相同

这是我的意思的一个例子:

{
    // Column : 1    2    3    4    5    6    7    8    9
    NUMBER : [ "1", "2", "3", "1", "2", "3", "1", "2", "3" ],
    LETTER : [ "A", "B", "C", "A", "E", "F", "G", "B", "I" ],
    SYMBOL : [ "!", "!", "!", "!", "!", "!", "!", "!", "!" ],
    ...
}

“垂直副本”可以是与任何前一列具有相同值的任何列。在上面的地图中,重复项将是列[1,4](值均为1,A,!)和[2,8](均值为2,B,!)。

删除“垂直重复”后,上面地图的输出:

{
    // Previous Column:
    //          1    2    3    5    6    7    9
    NUMBER : [ "1", "2", "3", "2", "3", "1", "3" ],
    LETTER : [ "A", "B", "C", "E", "F", "G", "I" ],
    SYMBOL : [ "!", "!", "!", "!", "!", "!", "!" ],
    ...
}

是否有一种简单的方法可以删除“垂直重复”?我正在使用具有不同键集大小的多值映射(一个映射可能有3个不同的枚举键,另一个可能有17个不同的枚举键),以及不同的值集大小(一个映射可能包含每个列表的列表)大小为2,另一个可能包含每个大小为20的列表。

2 个答案:

答案 0 :(得分:2)

我建议使用基于列的数据结构而不是基于行的数据。至少你可以/应该使用这样的结构进行这个操作,然后你可以添加一个简单的方法,然后将它变回行式多图。这就是它在完整功能示例中的样子:

public enum Row {
    NUMBER, LETTER, SYMBOL, WHATEVER1, WHATEVER2
}

public static class Col {
    Map<Row, String> col = new HashMap<>();

    public Col(Entry<Row, String>... entries) {
        for (Entry<Row, String> entry: entries) {
            col.put(entry.getKey(), entry.getValue());
        }
    }

    // to use within a LinkedHashSet
    @Override
    public boolean equals(Object other) {
        if (this == other) return true;
        if (other == null || getClass() != other.getClass()) return false;
        return Objects.equals(col, ((Col) other).col);
    }

    @Override
    public int hashCode() { return Objects.hash(col); }

    @Override
    public String toString() { return col.toString(); }
}


public static void main(String[] argv) {
    // alternatively use LinkedHashSet directly
    List<Col> cols = new ArrayList<>();
    cols.add(new Col(new SimpleEntry<>(Row.NUMBER, "1"), new SimpleEntry<>(Row.LETTER, "A"), new SimpleEntry<>(Row.WHATEVER1, "X")));
    cols.add(new Col(new SimpleEntry<>(Row.NUMBER, "2"), new SimpleEntry<>(Row.LETTER, "B"), new SimpleEntry<>(Row.SYMBOL, "!")));
    cols.add(new Col(new SimpleEntry<>(Row.NUMBER, "1"), new SimpleEntry<>(Row.LETTER, "A"), new SimpleEntry<>(Row.WHATEVER1, "X")));

    // turn original structure unique keeping order of insertion
    Set<Col> unique = new LinkedHashSet<>(cols);

    System.out.println(unique);
}

打印

  

[{LETTER = A,NUMBER = 1,WHATEVER1 = X},{LETTER = B,NUMBER = 2,SYMBOL =!}]

答案 1 :(得分:0)

根据时间或空间限制,有不同的方法,但您可以为每个列值(例如Map<String, Integer>)构建直方图,并删除计数为2或更多的所有列。这应该比将每列与每列其他列进行比较更有效。