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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从多值映射中删除“垂直重复”值?相关的知识,希望对你有一定的参考价值。

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

答案

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

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

另一答案

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

以上是关于如何从多值映射中删除“垂直重复”值?的主要内容,如果未能解决你的问题,请参考以下文章

将 Solr 重复值删除到多值字段中

对象关系映射中的多值属性(Android 应用程序)

如何从多阵列中删除文件详细信息

如何仅从多对多映射表加载 id?

多映射通用集合类(C#实现)--支持一键多值存储

Access 2013:删除包含多值字段的记录的正确方法是啥?