Nauka Scali jest obecnie potrzebna do odwrócenia mapy, aby wykonać kilka odwróconych wartości-> wyszukiwania kluczy. Szukałem prostego sposobu na zrobienie tego, ale wymyśliłem tylko:
(Map() ++ origMap.map(kvp=>(kvp._2->kvp._1)))
Czy ktoś ma bardziej eleganckie podejście?
scala
scala-collections
AlexeyMK
źródło
źródło
Map(1 -> "A", 2 -> "B", 3 -> "B").map(_.swap)
daje wynikMap(A -> 1, B -> 3)
Matematycznie mapowanie może nie być odwracalne (iniekcyjne), np. Z
Map[A,B]
, którego nie można pobraćMap[B,A]
, ale raczej otrzymujemyMap[B,Set[A]]
, ponieważ mogą być różne klucze powiązane z tymi samymi wartościami. Jeśli więc chcesz poznać wszystkie klucze, oto kod:źródło
.map(_._1)
byłby bardziej czytelny jako sprawiedliwy.keys
Set
s zamiastList
s, jak poprzednio..mapValues
ponieważ zwraca widok. Czasami tego chcesz, ale jeśli nie będziesz ostrożny, może to zająć dużo pamięci i procesora. Aby zmusić go do mapy, można to zrobićm.groupBy(_._2).mapVaues(_.keys).map(identity)
, czy można zastąpić wezwanie do.mapValues(_.keys)
z.map { case (k, v) => k -> v.keys }
.Możesz uniknąć rzeczy ._1 podczas iteracji na kilka sposobów.
Oto jeden sposób. Używa częściowej funkcji, która obejmuje jedyny przypadek, który ma znaczenie dla mapy:
Oto inny sposób:
Iteracja mapy wywołuje funkcję z dwuelementową krotką, a funkcja anonimowa potrzebuje dwóch parametrów. Function.tupled dokonuje tłumaczenia.
źródło
Przyszedłem tutaj, szukając sposobu na odwrócenie mapy typu Map [A, Seq [B]] na Map [B, Seq [A]], gdzie każdy B na nowej mapie jest powiązany z każdym A na starej mapie dla które B było zawarte w sekwencji skojarzonej z A.
Np.
Map(1 -> Seq("a", "b"), 2-> Seq("b", "c"))
Odwróciłby się do
Map("a" -> Seq(1), "b" -> Seq(1, 2), "c" -> Seq(2))
Oto moje rozwiązanie:
gdzie staraMapa jest typu,
Map[A, Seq[B]]
a nowaMapa jest typuMap[B, Seq[A]]
Zagnieżdżone foldLefts sprawiają, że trochę się wzdrygam, ale jest to najprostszy sposób na wykonanie tego typu inwersji. Czy ktoś ma czystsze rozwiązanie?
źródło
Map[A, Seq[B]]
naMap[B, Seq[A]]
którym swoimi trasnforms roztwórMap[A, Seq[B]]
doMap[Seq[B], Seq[A]]
.a.toSeq.flatMap { case (a, b) => b.map(_ -> a) }.groupBy(_._2).mapValues(_.map(_._1))
OK, więc jest to bardzo stare pytanie z wieloma dobrymi odpowiedziami, ale zbudowałem ostateczny, uniwersalny, szwajcarski scyzoryk,
Map
falownik i jest to miejsce, w którym można to opublikować.Właściwie to dwa falowniki. Jeden dla poszczególnych elementów wartości ...
... i inny, całkiem podobny, dla kolekcji wartościowych.
stosowanie:
Wolałbym mieć obie metody w tej samej niejawnej klasie, ale im więcej czasu poświęcałem na jej badanie, tym bardziej wydawało się to problematyczne.
źródło
Możesz odwrócić mapę używając:
Problem z tym podejściem polega na tym, że jeśli wartości, które stały się kluczami mieszania na mapie, nie są unikalne, zduplikowane wartości zostaną usunięte. Ilustrować:
Aby tego uniknąć, możesz najpierw przekonwertować mapę na listę krotek, a następnie odwrócić, aby nie upuścić żadnych zduplikowanych wartości:
źródło
W scali REPL:
Zwróć uwagę, że zduplikowane wartości zostaną zastąpione ostatnim dodatkiem do mapy:
źródło
Zaczynając
Scala 2.13
, aby zamienić klucz / wartości bez utraty kluczy skojarzonych z tymi samymi wartościami, możemy skorzystać zMap
nowej metody groupMap , która (jak sama nazwa wskazuje) jest odpowiednikiemgroupBy
aimap
ping na zgrupowanych elementach.To:
group
elementy s oparte na drugiej części krotki (_._2
) (część grupowa mapy grupy )map
s pogrupowane elementy, biorąc ich pierwszą część krotki (_._1
) (część mapy grupy mapy )Może to być postrzegane jako wersja jednego przejścia z
map.groupBy(_._2).mapValues(_.map(_._1))
.źródło
Map[K, C[V]]
sięMap[V, C[K]]
.Odwrotna to lepsza nazwa dla tej operacji niż odwrotna (np. „Odwrotność funkcji matematycznej”)
Często wykonuję tę odwrotną transformację nie tylko na mapach, ale na innych kolekcjach (w tym Seq). Uważam, że najlepiej nie ograniczać definicji mojej operacji odwrotnej do map jeden do jednego. Oto definicja, z jaką operuję dla map (proszę sugerować ulepszenia mojej implementacji).
Jeśli jest to mapa jeden do jednego, otrzymujesz listy singletonów, które można trywialnie przetestować i przekształcić w Mapę [B, A], a nie Map [B, List [A]].
źródło
Możemy spróbować użyć tej
foldLeft
funkcji, która zajmie się kolizjami i odwróci mapę w pojedynczym przejściu.źródło