Sök…


Destrukturera en vektor

Så här kan du förstöra en vektor:

(def my-vec [1 2 3])

Därefter, exempelvis inom en let blocket, kan du extrahera värden från vektorn mycket kortfattat på följande sätt:

(let [[x y] my-vec]
 (println "first element:" x ", second element: " y))
;; first element: 1 , second element: 2

Destrukturera en karta

Så här kan du förstöra en karta:

(def my-map {:a 1 :b 2 :c 3})

Sedan, till exempel, inom ett låtblock kan du extrahera värden från kartan mycket kortfattat enligt följande:

(let [{x :a y :c} my-map]
  (println ":a val:" x ", :c val: " y))
;; :a val: 1 , :c val: 3

Lägg märke till att värdena som extraheras i varje kartläggning är till vänster och knapparna de är associerade med till höger.

Om du vill förstöra värden på bindningar med samma namn som tangenterna kan du använda den här genvägen:

(let [{:keys [a c]} my-map]
  (println ":a val:" a ", :c val: " c))
;; :a val: 1 , :c val: 3

Om dina nycklar är strängar kan du använda nästan samma struktur:

(let [{:strs [foo bar]} {"foo" 1 "bar" 2}]
  (println "FOO:" foo  "BAR: " bar ))
;; FOO: 1 BAR: 2

Och på liknande sätt för symboler:

(let [{:syms [foo bar]} {'foo 1 'bar 2}]
  (println "FOO:" foo "BAR:" bar))
;; FOO: 1 BAR: 2

Om du vill förstöra en kapslad karta kan du bo boformer som förklaras ovan:

(def data
  {:foo {:a 1
         :b 2}
   :bar {:a 10
         :b 20}})

(let [{{:keys [a b]} :foo
       {a2 :a b2 :b} :bar} data]
  [a b a2 b2])
;; => [1 2 10 20]

Förstör resterande element i en sekvens

Låt oss säga att du har en sådan vektor:

(def my-vec [1 2 3 4 5 6])

Och du vill extrahera de tre första elementen och få de återstående elementen som en sekvens. Detta kan göras på följande sätt:

(let [[x y z & remaining] my-vec]
 (println "first:" x ", second:" y "third:" z "rest:" remaining))
;= first: 1 , second: 2 third: 3 rest: (4 5 6)

Destrukturera kapslade vektorer

Du kan förstöra kapslade vektorer:

(def my-vec [[1 2] [3 4]])

(let [[[a b][c d]] my-vec]
  (println a b c d))
;; 1 2 3 4

Destrukturera en karta med standardvärden

Ibland vill du förstöra nyckeln under en karta som kanske inte finns på kartan, men du vill ha ett standardvärde för det förstörda värdet. Du kan göra det på detta sätt:

(def my-map {:a 3 :b 4})
(let [{a :a
       b :b
       :keys [c d]
       :or {a 1
            c 2}} my-map]
  (println a b c d))
  ;= 3 4 2 nil

Förstörande params av en fn

Destructurling fungerar på många platser såväl som i param listan över en fn:

(defn my-func [[_ a b]]
  (+ a b))

(my-func [1 2 3]) ;= 5
(my-func (range 5)) ;= 3

Destrukturering fungerar också för & rest konstruktionen i param listan:

(defn my-func2 [& [_ a b]]
  (+ a b))

(my-func2 1 2 3) ;= 5
(apply my-func2 (range 5)) ;= 3

Konvertera resten av en sekvens till en karta

Destrukturering ger dig också möjligheten att tolka en sekvens som en karta:

(def my-vec [:a 1 :b 2])
(def my-lst '("smthg else" :c 3 :d 4))

(let [[& {:keys [a b]}] my-vec
      [s & {:keys [c d]} my-lst]
  (+ a b c d)) ;= 10

Det är användbart för att definiera funktioner med namngivna parametrar :

(defn my-func [a b & {:keys [c d] :or {c 3 d 4}}]
  (println a b c d))

(my-func 1 2) ;= 1 2 3 4
(my-func 3 4 :c 5 :d 6) ;= 3 4 5 6

Översikt

Destrukturering låter dig extrahera data från olika objekt i olika variabler. I varje exempel nedan tilldelas varje variabel sin egen sträng ( a = "a" , b = "b" , & c.)

Typ Exempel Värde på data / kommentar
vec (let [[abc] data ...) ["a" "b" "c"]
kapslad vec (let [[[ab] [cd]] data ...) [["a" "b"] ["c" "d"]]
map (let [{a :ab :bc :c} data ...) {:a "a" :b "b" :c "c"}
- alternativ: (let [{:keys [abc]} data ...) När variabler namnges efter tangenterna.

tips:

Destrukturering och bindning till nycklarnas namn

Ibland när du förstör kartor vill du binda de förstörda värdena till deras respektive nyckelnamn. Beroende på datorns uppbyggnadsgrad, kan användningen av standardförstörningsschemat vara lite ordboken .

Låt oss säga, vi har en kartbaserad post som så:

(def john {:lastname "McCarthy" :firstname "John" :country "USA"})

vi skulle normalt förstöra det så:

(let [{lastname :lastname firstname :firstname country :country} john]
    (str firstname " " lastname ", " country))
;;"John McCarthy, USA"

här är datastrukturen ganska enkel med bara 3 platser ( förnamn, efternamn, land ) men föreställ dig hur besvärligt det skulle vara om vi var tvungna att upprepa alla nyckelnamn två gånger för mer granulerad datastruktur (med väldigt fler slots än bara 3) .

I stället är ett bättre sätt att hantera detta genom att använda :keys (eftersom våra nycklar är nyckelord här) och välja det nyckelnamn vi vill binda till så:

(let [{:keys [firstname lastname country]} john]
    (str firstname " " lastname ", " country))
;;"John McCarthy, USA"

Samma intuitiva logik gäller för andra nyckeltyper som symboler (med :syms ) och vanliga gamla strängar (med :strs )

;; using strings as keys
(def john {"lastname" "McCarthy" "firstname" "John" "country" "USA"})
;;#'user/john

;; destructuring string-keyed map
(let [{:strs [lastname firstname country]} john]
    (str firstname " " lastname ", " country))
;;"John McCarthy, USA"

;; using symbols as keys
(def john {'lastname "McCarthy" 'firstname "John" 'country "USA"})

;; destructuring symbol-keyed map
(let [{:syms [lastname firstname country]} john]
    (str firstname " " lastname ", " country))
;;"John McCarthy, USA"

Destrukturera och ge ett namn på det ursprungliga argumentvärdet

(defn print-some-items 
   [[a b :as xs]]
  (println a)
  (println b)
  (println xs))

(print-some-items [2 3])

Det här exemplet skriver ut utgången

2
3
[2 3]

Argumentet är förstört och artiklarna 2 och 3 tilldelas symbolerna a och b . Det ursprungliga argumentet, hela vektorn [2 3] , tilldelas också symbolen xs .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow