【问题标题】:How to remove "vertical duplicate" values from multi-value map?如何从多值映射中删除“垂直重复”值?
【发布时间】:2018-03-03 19:01:18
【问题描述】:

不幸的是,我正在使用 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 的列表)。

【问题讨论】:

    标签: java dictionary data-structures


    【解决方案1】:

    我建议对这些数据使用基于列的数据结构,而不是基于行的数据结构。至少您可以/应该为此操作使用这样的结构,并且您可以添加一个简单的方法,然后将其转换回逐行多映射。这是一个完整功能示例的样子:

    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=!}]

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-15
        • 2018-01-18
        • 2019-12-08
        • 2019-09-22
        • 2017-11-07
        • 1970-01-01
        相关资源
        最近更新 更多