Saya ingin memetakan fungsi pada semua tombol di kamus. Saya berharap sesuatu seperti yang berikut ini akan berfungsi, tetapi filter tidak dapat diterapkan ke kamus secara langsung. Apa cara paling bersih untuk mencapai ini?
Dalam contoh ini, saya mencoba untuk menambah setiap nilai dengan 1. Namun ini insidental untuk contoh - tujuan utamanya adalah untuk mengetahui cara menerapkan peta () ke kamus.
var d = ["foo" : 1, "bar" : 2]
d.map() {
$0.1 += 1
}
swift
dictionary
Maria Zverina
sumber
sumber
map
dilakukan. apa yang Anda minta adalah cara menyembunyikan iterasi di balik ekstensi / penutupan sehingga Anda tidak perlu melihatnya setiap kali Anda menggunakannya.Jawaban:
Swift 4+
Kabar baik! Swift 4 mencakup
mapValues(_:)
metode yang membangun salinan kamus dengan tombol yang sama, tetapi nilainya berbeda. Ini juga termasukfilter(_:)
kelebihan yang mengembalikan aDictionary
, daninit(uniqueKeysWithValues:)
daninit(_:uniquingKeysWith:)
initializers untuk membuatDictionary
dari urutan tuple yang sewenang-wenang. Itu berarti, jika Anda ingin mengubah kunci dan nilai, Anda bisa mengatakan sesuatu seperti:Ada juga API baru untuk menggabungkan kamus bersama, menggantikan nilai default untuk elemen yang hilang, mengelompokkan nilai-nilai (mengubah koleksi menjadi kamus array, dikunci oleh hasil pemetaan koleksi atas beberapa fungsi), dan banyak lagi.
Selama diskusi proposal, SE-0165 , yang memperkenalkan fitur-fitur ini, saya mengemukakan jawaban Stack Overflow ini beberapa kali, dan saya pikir banyaknya upvotes membantu menunjukkan permintaan. Jadi terima kasih atas bantuan Anda membuat Swift lebih baik!
sumber
map
yang dapat menghasilkan kunci yang saling bertentangan masih bergunamap
dalam banyak situasi. (Di sisi lain, Anda bisa berargumen bahwa memetakan hanya nilai-nilai adalah interpretasi alamimap
pada kamus-baik contoh poster asli dan milik saya hanya mengubah nilai-nilai, dan secara konseptual,map
pada array hanya memodifikasi nilai-nilai, bukan indeks.)try
:return Dictionary<Key, OutValue>(try map { (k, v) in (k, try transform(v)) })
DictionaryExtension.swift:13:16: Argument labels '(_:)' do not match any available overloads
Argument labels '(_:)' do not match any available overloads
ketika menerapkan ekstensi terakhir itu. Tidak benar-benar yakin bagaimana menyelesaikannya: /Dictionary
penginisialisasi yang ditambahkan dalam salah satu contoh sebelumnya. Pastikan Anda memasukkan keduanya.Dengan Swift 5, Anda dapat menggunakan salah satu dari lima cuplikan berikut untuk menyelesaikan masalah Anda.
# 1. Menggunakan
Dictionary
mapValues(_:)
metode# 2. Menggunakan
Dictionary
map
metode daninit(uniqueKeysWithValues:)
penginisialisasi# 3. Menggunakan
Dictionary
reduce(_:_:)
metode ataureduce(into:_:)
metode# 4 Menggunakan
Dictionary
subscript(_:default:)
subskrip# 5 Menggunakan
Dictionary
subscript(_:)
subskripsumber
Sementara sebagian besar jawaban di sini fokus pada cara memetakan seluruh kamus (kunci dan nilai), pertanyaannya hanya ingin memetakan nilai. Ini adalah perbedaan penting karena nilai pemetaan memungkinkan Anda untuk menjamin jumlah entri yang sama, sedangkan pemetaan kedua kunci dan nilai dapat menghasilkan kunci duplikat.
Berikut ini ekstensi,,
mapValues
yang memungkinkan Anda untuk memetakan nilai-nilai saja. Catatan juga memperluas kamus denganinit
dari urutan pasangan kunci / nilai, yang sedikit lebih umum daripada menginisialisasi dari array:sumber
func mapValues<T>(_ transform: (_ value: Value) -> T) -> [Key: T] { var result = [Key: T]() for (key, val) in self { result[key] = transform(val) } return result }
. Saya menemukan itu juga lebih baik. Apakah ada masalah kinerja?Cara terbersih adalah menambahkan
map
Kamus:Memeriksa apakah itu berfungsi:
Keluaran:
sumber
SequenceType.map
itu bukan fungsi yang bermutasi. Contoh Anda dapat ditulis ulang untuk mengikuti kontrak yang adamap
, tetapi itu sama dengan jawaban yang diterima.Anda juga bisa menggunakan
reduce
alih-alih peta.reduce
mampu melakukan apa pun yangmap
bisa dilakukan dan banyak lagi!Akan cukup mudah untuk membungkus ini dalam ekstensi, tetapi bahkan tanpa ekstensi itu memungkinkan Anda melakukan apa yang Anda inginkan dengan satu panggilan fungsi.
sumber
let newDict = oldDict.reduce([String:Int]()) { (var dict, pair) in dict["new\(pair.1)"] = pair.1; return dict }
Ternyata Anda bisa melakukan ini. Yang harus Anda lakukan adalah membuat array dari yang
MapCollectionView<Dictionary<KeyType, ValueType>, KeyType>
kembali darikeys
metode kamus . ( Info di sini ) Anda kemudian dapat memetakan array ini, dan meneruskan nilai yang diperbarui kembali ke kamus.sumber
Menurut Referensi Perpustakaan Standar Swift, peta adalah fungsi dari array. Bukan untuk kamus.
Tetapi Anda dapat mengulangi kamus Anda untuk memodifikasi kunci:
sumber
Saya sedang mencari cara untuk memetakan kamus langsung ke Array yang diketik dengan objek khusus. Temukan solusinya dalam ekstensi ini:
Menggunakannya sebagai berikut:
sumber
Cepat 3
Saya mencoba cara mudah di Swift 3.
Saya ingin peta [String: String] ke [String: String] , saya menggunakan forEach bukan peta atau peta datar.
sumber
Cepat 5
fungsi peta kamus dilengkapi dengan sintaks ini.
dictData.map(transform: ((key: String, value: String)) throws -> T)
Anda bisa mengatur nilai penutupan untuk ini
Output akan ::
Mungkin memberi peringatan ini
Result of call to 'map' is unused
Kemudian cukup atur
_ =
sebelum variabel.Mungkin itu akan membantu Anda Terima kasih.
sumber
Saya berasumsi masalahnya adalah menjaga kunci kamus asli kami dan memetakan semua nilainya dengan cara tertentu.
Mari kita generalisasi dan katakan bahwa kita mungkin ingin memetakan semua nilai ke tipe lain .
Jadi yang ingin kita mulai adalah kamus dan penutup (fungsi) dan berakhir dengan kamus baru. Masalahnya adalah, tentu saja, pengetikan ketat Swift menghalangi. Penutupan perlu menentukan jenis apa yang masuk dan jenis apa yang keluar, dan dengan demikian kita tidak bisa membuat metode yang mengambil jenderal penutupan - kecuali dalam konteks generik. Jadi kita membutuhkan fungsi generik.
Solusi lain telah berkonsentrasi pada melakukan hal ini dalam dunia generik Kamus generic struct itu sendiri, tetapi saya merasa lebih mudah untuk berpikir dalam hal fungsi tingkat atas. Sebagai contoh, kita bisa menulis ini, di mana K adalah tipe kunci, V1 adalah tipe nilai kamus awal, dan V2 adalah tipe nilai kamus akhir:
Berikut adalah contoh sederhana menyebutnya, hanya untuk membuktikan bahwa generik memang menyelesaikan sendiri pada waktu kompilasi:
Kami mulai dengan kamus
[String:Int]
dan berakhir dengan kamus[String:String]
dengan mengubah nilai-nilai kamus pertama melalui penutupan.(EDIT: Saya melihat sekarang bahwa ini secara efektif sama dengan solusi AirspeedVelocity, kecuali bahwa saya tidak menambahkan keanggunan ekstra dari penginisialisasi Kamus yang membuat Kamus keluar dari urutan zip.)
sumber
Cepat 3
Pemakaian:
Perpanjangan:
sumber
Jika Anda hanya mencoba memetakan nilai (berpotensi mengubah tipenya), sertakan ekstensi ini:
Mengingat Anda memiliki kamus ini:
Transformasi nilai single-line kemudian terlihat seperti ini:
Transformasi nilai multi-garis kemudian terlihat seperti ini:
sumber
Pendekatan lain adalah dengan
map
kamus danreduce
, di mana fungsikeyTransform
danvalueTransform
fungsi.sumber
Swift 3 saya menggunakan ini,
Pemakaian:
Ref
sumber