Clojure-da y qiymatini xarf xarfini qanday yangilash kerak?

Men Clojure'da xarita, x va y qiymatlarini parametr sifatida qabul qiladigan va keyin barcha xarflarni xarita yordamida olib boradigan va barcha x qiymatlarini (mavjud bo'lsa) y bilan almashtirishga harakat qilmoqchiman.

(defn Change-x-to-y-in-map [map x y]; code here)

Masalan, agar {: a 1: b 2: c 1} kabi xaritani topsam va funktsiyani parametr bilan [map1 "works it!"] Deb chaqirsa, funksiya quyidagi xarita: {: a "ishlaydi!" : b 2: c "ishlaydi!} .

Shunday qilib, barcha kalitlarni 1 qiymati bilan o'zgartiradi va "ishlaydi!"

Sizning yordamingiz uchun oldindan rahmat!

0
fmap funktsiyasini ko'rib chiqaylik, buni bajaradi: github.com/clojure/algo.generic/blob/…
qo'shib qo'ydi muallif Josh, manba
Bu ideal bo'lmagan xaritani chiziqli qidirishni talab qiladi. Buni ta'kidlab, bu xarita </​​code> yoki uchun yordamida trivially bajarilishi mumkin. Siz ulardan birortasini qo'llamoqchimisiz?
qo'shib qo'ydi muallif Carcigenicate, manba

6 javoblar

map-vals funktsiyasi allaqachon Tupelo kutubxonasida mavjud. Xaritadagi har bir qiymatga tx-fn funksiyasi kiradi va yangi chiqish xaritasi yaratiladi. Birlik testlari uni amalda ko'rsatadi:

  (let [map-123 {:a 1 :b 2 :c 3}
        tx-fn   {1 101 2 202 3 303}]
    (is= (t/map-vals map-123 inc)   {:a   2, :b   3, :c   4})
    (is= (t/map-vals map-123 tx-fn) {:a 101, :b 202, :c 303}))

Birinchi holda, kirish kodi (IM) ning har bir qiymatiga inc funktsiyasi qo'llaniladi.

2-misol, har bir [k v] jufti oldindan yangi qiymatlarga, ehtimol, IMda kerakli o'zgarishlarni ko'rsatadigan "kod" tx-fn sifatida "transformation map" dan foydalanadi. Shunday qilib, map-123 ning qiymatlari quyidagicha o'zgardi:

1 -> 101
2 -> 202 
3 -> 303

Birodar vazifasi map-keys ham mavjud:

(dotest
  (let [map-123 {1 :a 2 :b 3 :c}
        tx-fn   {1 101 2 202 3 303}]
    (is= (t/map-keys map-123 inc)   {  2 :a   3 :b   4 :c})
    (is= (t/map-keys map-123 tx-fn) {101 :a 202 :b 303 :c}))
2
qo'shib qo'ydi

Stefanning javobidan boshlab, biz yangi xaritani yaratish o'rniga birinchi xarita o'zgartirishimiz mumkin:

(defn update-v [m ov nv] 
  (reduce-kv (fn [acc k v] (if (= v ov) (assoc acc k nv) acc))
             m m))

O'zgarishlar qilish uchun vaqtincha foydalanishimiz mumkin:

(defn update-v [m ov nv] 
  (persistent!
    (reduce-kv (fn [acc k v] (if (= v ov) (assoc! acc k nv) acc))
             (transient m) m)))

Ushbu o'zgarishlar (hmmmmmm) tezlikni kamaytirish kerak.

(Agar siz ushbu kodni CC-BY SA ostida olmoqchi bo'lsangiz, ushbu kodni Apache 2.0 litsenziyasi ostiga qo'yaman)

2
qo'shib qo'ydi
@StefanKamphausen bajarildi.
qo'shib qo'ydi muallif Thumbnail, manba
Meni yaxshi ko'radi. Siz uni ASL ostiga qo'yasizmi? Aks holda, OP sizga CSS-dan tashqari kengaytmalarni ishlata olmaydi.
qo'shib qo'ydi muallif Stefan Kamphausen, manba

clojure.walk vazifalari:

(defn replace-vals [m v r]
  (walk/postwalk
    (fn [e] (if (= e v) r e))
    m))

(replace-vals {:a 1 :b 2 :c 1} 1 "Hey!")
=> {:a "Hey!", :b 2, :c "Hey!"}

(replace-vals [1 2 3 4 1] 1 "Hey!")
=> ["Hey!" 2 3 4 "Hey!"]

Bu shuningdek, ichki shakllar uchun ham ishlaydi.

(replace-vals {:a 1 :b {:c 1 :d "Bye!"}} 1 "Hey!")
=> {:a "Hey!", :b {:c "Hey!", :d "Bye!"}}

Agar siz faqat qiymatlari xarfini almashtirishni istasangiz, buni qayta ko'rib chiqishingiz mumkin:

(defn replace-map-vals [m v r]
  (walk/prewalk
    (fn [e] (if (and (map-entry? e) (= (val e) v))
              [(key e) r]
              e))
    m))

(replace-map-vals {1 "not replaced" :replaced 1} 1 "Hey!")
=> {1 "not replaced", :replaced "Hey!"})

bilan bog'liq muammo tufayli, ushbu versiya prewalk postwalk va xarita yozuvlari .

2
qo'shib qo'ydi
Qiziqarli. Postwalk faqat kalitlarga emas, balki kalitlarga qaraydi?
qo'shib qo'ydi muallif johnbakers, manba
Agar k/v juftligi bo'lsa, (fn [e] (if (= e v) r e)) bu kalitni istisno qiladigan qiymat v uchun qanday bo'lishi mumkin?
qo'shib qo'ydi muallif johnbakers, manba
Boshqacha qilib aytganda, sizning namunangizga ko'ra, xaritadagi birinchi versiyangiz namunasi nima uchun ishlaydi? Xaritalarda sizning ikkinchi versiyangiz bilan bir xil funktsionallik mavjud, lekin qanday qilib bunday bo'lishi mumkinligini ko'rmayapman. Har ikki versiya ham ikkinchi versiya emas, balki qadriyatlarni almashtirmoqda.
qo'shib qo'ydi muallif johnbakers, manba
@johnbakers mening asl misolimdagi barcha qiymatlarga qaraydi, shuning uchun kalitlar qo'shiladi. Faqat prewalk dan foydalangan holda boshqa xarita xarita qiymatlarini almashtirishga urinib ko'rilgan.
qo'shib qo'ydi muallif Taylor Wood, manba
@johnbakers qanday o'tishni ko'rish uchun prewalk-demo yoki postwalk-demo dan foydalaning. Ha, funktsiyasi butun xarita yozuvini bir qadamda qabul qiladi, lekin u shuningdek, birma-bir kalit va qiymatni aylanib ketganda qabul qiladi.
qo'shib qo'ydi muallif Taylor Wood, manba

Redirect-friendly versiyasi to'g'ridan-to'g'ri reduce-kv dan foydalanadi:

(defn update-v [m ov nv] 
  (reduce-kv (fn [acc k v]
              (assoc acc k (if (= v ov) nv v)))
             {} m))

(update-v {:x 1 :y 2 :z 1} 1 "It Works!") => {:x "It Works!", :y 2, :z "It Works!"}

(Agar siz ushbu kodni CC-BY SA ostida olmoqchi bo'lsangiz, ushbu kodni Apache 2.0 litsenziyasi ostiga qo'yaman)

2
qo'shib qo'ydi
Talabni noto'g'ri qabul qildim: izoh yo'q qilindi.
qo'shib qo'ydi muallif Thumbnail, manba
Men bir necha taklifni oldim.
qo'shib qo'ydi muallif Thumbnail, manba
Bu to'g'ri. Xaritada yinelemeyen biron-bir yechim bilmasdim.
qo'shib qo'ydi muallif Stefan Kamphausen, manba

O'rnatish uchun Spektorli yechim:

(defn replace-vals [m v r] 
    (setval [MAP-VALS (partial = v)] r m))
0
qo'shib qo'ydi

Buning bir usuli, yangi xarita yaratish uchun uchun tugmachalari va qadriyatlari orqali yinelemek va kodni dan foydalaning:

(defn val-replace [m x y]
  (into {} (for [[k v] m]
             [k (if (= v x) y v)])))

> (val-replace {:x 1 :y 2 :z 1} 1 "It Works!")
{:x "It Works!", :y 2, :z "It Works!"}

> (val-replace1 {:a "" :b 4 :c ""} "" nil)
{:a nil, :b 4, :c nil}
0
qo'shib qo'ydi
Kechirasiz! Ruxsat etilgan. x o'rniga v if else ifodasida if edi.
qo'shib qo'ydi muallif jas, manba
Katta rahmat! Hozir u ishlaydi :)
qo'shib qo'ydi muallif Ville Lehtonen, manba