Jeśli mam kolekcję c
typu T
i nie ma właściwość p
na T
(typu P
, powiedzmy), co jest najlepszym sposobem, aby zrobić MAP-by-wydobycia kluczu ?
val c: Collection[T]
val m: Map[P, T]
Jeden sposób jest następujący:
m = new HashMap[P, T]
c foreach { t => m add (t.getP, t) }
Ale teraz potrzebuję mutowalnej mapy. Czy jest lepszy sposób na zrobienie tego, aby było to w jednej linii, a ja otrzymałem niezmienną mapę? (Oczywiście mógłbym zamienić powyższe w proste narzędzie biblioteczne, tak jak zrobiłbym to w Javie, ale podejrzewam, że w Scali nie ma takiej potrzeby)
scala
map
scala-collections
oxbow_lakes
źródło
źródło
Traversable[K].mapTo( K => V)
iTraversable[V].mapBy( V => K)
były lepsze!c
wc.iterator
celu utworzenia powodują unikanie gromadzenia pośredniej.Możesz skonstruować Mapę ze zmienną liczbą krotek. Więc użyj metody map na kolekcji, aby przekonwertować ją na kolekcję krotek, a następnie użyj sztuczki: _ *, aby przekonwertować wynik na zmienny argument.
źródło
Oprócz rozwiązania @James Iry można to również osiągnąć za pomocą fałdy. Podejrzewam, że to rozwiązanie jest nieco szybsze niż metoda krotki (powstaje mniej śmieci):
źródło
list.foldLeft(Map[String,Int]()) { (m,s) => m + (s -> s.length) }
. Należy pamiętać, że jeśli chcesz używać przecinka zbudować krotki, trzeba dodatkową parę nawiasów:((s, s.length))
.Można to zaimplementować niezmiennie i za pomocą pojedynczego przejścia, zwijając kolekcję w następujący sposób.
Rozwiązanie działa, ponieważ dodanie do niezmiennej mapy zwraca nową niezmienną mapę z dodatkowym wpisem, a ta wartość służy jako akumulator podczas operacji fold.
Kompromisem jest tutaj prostota kodu w porównaniu z jego wydajnością. Dlatego w przypadku dużych kolekcji to podejście może być bardziej odpowiednie niż użycie 2 implementacji przechodzenia, takich jak stosowanie
map
itoMap
.źródło
Inne rozwiązanie (może nie działać dla wszystkich typów)
pozwala to uniknąć tworzenia listy pośredników, więcej informacji tutaj: Scala 2.8 breakOut
źródło
To, co próbujesz osiągnąć, jest nieco nieokreślone.
Co się stanie, jeśli co najmniej dwa elementy
c
są takie samep
? Który element zostanie zmapowany do tegop
na mapie?Bardziej dokładnym sposobem spojrzenia na to jest przedstawienie mapy między
p
wszystkimic
przedmiotami, które ją zawierają:Można to łatwo osiągnąć dzięki groupBy :
Jeśli nadal potrzebujesz oryginalnej mapy, możesz na przykład zmapować
p
ją na pierwsząt
, która ją ma:źródło
collect
zamiastmap
. Npc.group(t => t.p) collect { case (Some(p), ts) => p -> ts.head }
. : . W ten sposób możesz robić takie rzeczy, jak spłaszczanie map, gdy klucz jest Option [_]..mapValues(_.head)
zamiast mapy.Prawdopodobnie nie jest to najskuteczniejszy sposób przekształcenia listy w mapę, ale sprawia, że kod wywołujący jest bardziej czytelny. Użyłem niejawnych konwersji, aby dodać metodę mapBy do listy:
Przykład kodu telefonicznego:
Należy zauważyć, że z powodu niejawnej konwersji kod wywołujący musi zaimportować implicitConversions scali.
źródło
Działa dobrze i jest bardzo intuicyjny
źródło
c
jako klucza (w pewnym sensie). Zwróć uwagę na „mapę”, ponieważ wynikowa kolekcja nie jest skalą,Map
ale tworzy kolejną listę / iterowalną listę krotek ... ale efekt jest taki sam dla celów PO. Nie dyskontowałbym prostoty, ale nie jest tak wydajne jakfoldLeft
rozwiązanie, ani nie jest prawdziwa odpowiedź na pytanie „przekształcanie w zbiór w mapę według klucza”A co powiesz na używanie zip i toMap?
źródło
Oto dwa bezsensowne sposoby na zrobienie tego:
źródło
Map.fromList $ map (bar &&& id) c
,Map.fromList $ map (bar >>= (,)) c
.To działa dla mnie:
Mapa musi być zmienna, a mapa musi zostać zwrócona, ponieważ dodanie do mapy zmiennej nie zwraca mapy.
źródło
val personsMap = persons.foldLeft(Map[Int, PersonDTO]()) { (m, p) => m + (p.id -> p) }
Mapa może być niezmienna, jak pokazano powyżej, ponieważ dodanie do niezmiennej mapy zwraca nową niezmienną mapę z dodatkowym wpisem. Ta wartość służy jako akumulator podczas operacji składania.użyj map () na kolekcji, a następnie toMap
źródło
W przypadku konwersji z Json String (odczyt pliku json) do scala Map
źródło