java 嵌套数据结构的通用转换

bvuwiixz  于 2023-05-12  发布在  Java
关注(0)|答案(3)|浏览(136)

有两种类型的转换我想应用到一些嵌套的数据结构:

  1. Map<X,Map<Y,Z>>转换为Map<Y,Map<X,Z>>
    例如:
Map.of("a", Map.of("X", 1, "Y", 2), 
       "b", Map.of("Y", 3))

应该转变为

Map.of("X", Map.of("a", 1),
       "Y", Map.of("a", 2, "b", 3))

1.Map<X,Set>以转换为Map<Y,Set>
例如:

Map.of("a", Set.of("X", "Y"), 
       "b", Set.of("Y", "Z"))

应该转变为

Map.of("X", Set.of("a"),
       "Y", Set.of("a", "b"),
       "Z", Set.of("b"))

我不知道这些转换的名称,也没有在我使用的任何JVM语言(主要是Java,有时候是Groovy和Clojure)中找到它们的实现,可能是因为我不知道要找什么。它们似乎是相当普遍的问题,我希望它们是非常知名的,并且已经在库甚至SDK中提供了解决方案。第一个是一个“转置”我猜,作为一个Map的Map可以被视为一个矩阵。

qltillow

qltillow1#

// Transpose a map of maps
Map<Y, Map<X, Z>> transpose(Map<X, Map<Y, Z>> map) {
  Map<Y, Map<X, Z>> transposed = new HashMap<>();
  for (Map.Entry<X, Map<Y, Z>> entry : map.entrySet()) {
    for (Map.Entry<Y, Z> innerEntry : entry.getValue().entrySet()) {
      transposed.computeIfAbsent(innerEntry.getKey(), k -> new HashMap<>()).put(entry.getKey(), innerEntry.getValue());
    }
  }
  return transposed;
}

// Flatten a map of sets
Map<Y, Set> flatten(Map<X, Set> map) {
  Map<Y, Set> flattened = new HashMap<>();
  for (Map.Entry<X, Set> entry : map.entrySet()) {
    flattened.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).addAll(entry.getValue());
  }
  return flattened;
}

希望这能帮上忙。

k4emjkb1

k4emjkb12#

我不认为你会在广泛可用的库中找到这样的转置OP,但是在普通的Groovy中建模它们是相当容易的:

def inp1 = [ a:[ X:1, Y:2 ], b:[ Y:3 ] ]
def res1 = inp1.inject( [:].withDefault{ [:] } ){ res, k, v ->
  v.each{ kk, vv -> res[ kk ][ k ] = vv  }
  res
}

assert res1.toString() == '[X:[a:1], Y:[a:2, b:3]]'

// -------------------------

def inp2 = [ a:[ "X", "Y" ] as Set, b:[ "Y", "Z" ] as Set ]
def res2 = inp2.inject( [:].withDefault{ new HashSet() } ){ res, k, v ->
  v.each{ vv -> res[ vv ] << k }
  res
}
assert res2.toString() == '[X:[a], Y:[a, b], Z:[b]]'
assert Set.isAssignableFrom( res2.X.class )
62lalag4

62lalag43#

在Clojure中,转换看起来像是:

(defn rotate-map [m]
  (reduce-kv (fn [m k1 m2]
               (reduce-kv (fn [m k2 v] (assoc-in m [k2 k1] v)) m m2))
  {} m))

(defn rotate-set [m]
  (reduce-kv (fn [m k s]
               (reduce (fn [m x]
                         (update m x (fnil conj #{}) k))
                       m s))
             {} m))

测试:

user=> (rotate-map '{a {x 1 y 2} b {y 3}})
{x {a 1}, y {a 2, b 3}}

user=> (rotate-set '{x #{a} y #{a b} z #{b}})
{a #{x y}, b #{y z}}

相关问题