Jika saya memiliki koleksi c
tipe T
dan ada properti p
di T
(tipe P
, katakanlah), apa cara terbaik untuk melakukan kunci peta-dengan-mengekstraksi ?
val c: Collection[T]
val m: Map[P, T]
Salah satu caranya adalah sebagai berikut:
m = new HashMap[P, T]
c foreach { t => m add (t.getP, t) }
Tapi sekarang aku butuh peta yang bisa berubah . Apakah ada cara yang lebih baik untuk melakukan ini sehingga itu dalam 1 baris dan saya berakhir dengan Peta abadi ? (Jelas saya bisa mengubah hal di atas menjadi utilitas perpustakaan sederhana, seperti yang saya lakukan di Jawa, tetapi saya menduga bahwa di Scala tidak perlu)
scala
map
scala-collections
oxbow_lakes
sumber
sumber
Traversable[K].mapTo( K => V)
danTraversable[V].mapBy( V => K)
lebih baik!c
denganc.iterator
untuk menghindari pembuatan koleksi perantara.Anda dapat membuat Peta dengan jumlah variabel tupel. Jadi gunakan metode peta pada koleksi untuk mengubahnya menjadi kumpulan tupel dan kemudian gunakan: _ * trik untuk mengubah hasilnya menjadi argumen variabel.
sumber
Selain solusi @James Iry, Anda juga dapat melakukannya menggunakan lipatan. Saya menduga bahwa solusi ini sedikit lebih cepat daripada metode tuple (lebih sedikit objek sampah yang dibuat):
sumber
list.foldLeft(Map[String,Int]()) { (m,s) => m + (s -> s.length) }
. Catatan bahwa jika Anda ingin menggunakan koma untuk membangun tupel, Anda perlu tambahan sepasang kurung:((s, s.length))
.Ini dapat diimplementasikan secara kekal dan dengan satu traversal dengan melipat melalui koleksi sebagai berikut.
Solusinya bekerja karena menambahkan ke Peta yang tidak dapat diubah mengembalikan Peta yang tidak bisa diubah baru dengan entri tambahan dan nilai ini berfungsi sebagai akumulator melalui operasi lipat.
Yang menarik di sini adalah kesederhanaan kode versus efisiensinya. Jadi, untuk koleksi besar, pendekatan ini mungkin lebih cocok daripada menggunakan 2 implementasi traversal seperti menerapkan
map
dantoMap
.sumber
Solusi lain (mungkin tidak bekerja untuk semua jenis)
ini menghindari pembuatan daftar perantara, info lebih lanjut di sini: Scala 2.8 breakOut
sumber
Apa yang ingin Anda capai sedikit tidak terdefinisi.
Bagaimana jika dua atau lebih item yang
c
dibagikan samap
? Item mana yang akan dipetakan dengan yang adap
di peta?Cara yang lebih akurat untuk melihat ini adalah menghasilkan peta antara
p
dan semuac
item yang memilikinya:Ini dapat dengan mudah dicapai dengan groupBy :
Jika Anda masih menginginkan peta asli, Anda dapat, misalnya, memetakan
p
ke yang pertamat
memilikinya:sumber
collect
bukanmap
. Misalnya:c.group(t => t.p) collect { case (Some(p), ts) => p -> ts.head }
. Dengan cara ini Anda dapat melakukan hal-hal seperti meratakan peta ketika kunci Anda adalah Opsi [_]..mapValues(_.head)
alih-alih peta.Ini mungkin bukan cara yang paling efisien untuk mengubah daftar menjadi peta, tetapi itu membuat kode panggilan lebih mudah dibaca. Saya menggunakan konversi implisit untuk menambahkan metode mapBy ke Daftar:
Contoh kode panggilan:
Perhatikan bahwa karena konversi implisit, kode pemanggil perlu mengimpor konversi implisit scala.
sumber
Bekerja dengan baik dan sangat intuitif
sumber
c
sebagai kunci (semacam). Catatan "peta" karena koleksi yang dihasilkan bukan scalaMap
tetapi membuat daftar lain / itupable dari tuple ... tetapi efeknya sama untuk tujuan OP saya tidak akan mengabaikan kesederhanaan tetapi tidak seefisienfoldLeft
solusi, juga tidak efisien jawaban sesungguhnya untuk pertanyaan "mengubah menjadi koleksi menjadi peta-oleh-kunci"Bagaimana dengan menggunakan zip dan toMap?
sumber
Untuk apa nilainya, berikut adalah dua cara sia-sia melakukannya:
sumber
Map.fromList $ map (bar &&& id) c
,Map.fromList $ map (bar >>= (,)) c
.Ini bekerja untuk saya:
Peta harus bisa berubah dan Peta harus kembali karena menambahkan ke Peta yang bisa berubah tidak mengembalikan peta.
sumber
val personsMap = persons.foldLeft(Map[Int, PersonDTO]()) { (m, p) => m + (p.id -> p) }
Peta dapat berubah, seperti dibuktikan di atas, karena menambahkan ke Peta abadi mengembalikan Peta abadi baru dengan entri tambahan. Nilai ini berfungsi sebagai akumulator melalui operasi lipatan.gunakan peta () pada koleksi diikuti dengan toMap
sumber
Jika mengkonversi dari Json String (membaca file json) ke scala Map
sumber