clojure
Clojure-Destrukturierung
Suche…
Einen Vektor zerstören
So zerstören Sie einen Vektor:
(def my-vec [1 2 3])
Dann können Sie beispielsweise innerhalb eines let
Blocks Werte wie folgt aus dem Vektor extrahieren:
(let [[x y] my-vec]
(println "first element:" x ", second element: " y))
;; first element: 1 , second element: 2
Eine Karte zerstören
So zerstören Sie eine Karte:
(def my-map {:a 1 :b 2 :c 3})
Dann können Sie beispielsweise innerhalb eines Let-Blocks Werte wie folgt aus der Karte extrahieren:
(let [{x :a y :c} my-map]
(println ":a val:" x ", :c val: " y))
;; :a val: 1 , :c val: 3
Beachten Sie, dass sich die Werte, die in jedem Mapping extrahiert werden, links und die Schlüssel, denen sie zugeordnet sind, rechts befinden.
Wenn Sie Werte zu Bindungen mit denselben Namen wie die Tasten zerstören möchten, können Sie diese Verknüpfung verwenden:
(let [{:keys [a c]} my-map]
(println ":a val:" a ", :c val: " c))
;; :a val: 1 , :c val: 3
Wenn Ihre Schlüssel Zeichenfolgen sind, können Sie fast dieselbe Struktur verwenden:
(let [{:strs [foo bar]} {"foo" 1 "bar" 2}]
(println "FOO:" foo "BAR: " bar ))
;; FOO: 1 BAR: 2
Und ähnlich für Symbole:
(let [{:syms [foo bar]} {'foo 1 'bar 2}]
(println "FOO:" foo "BAR:" bar))
;; FOO: 1 BAR: 2
Wenn Sie eine verschachtelte Karte zerstören möchten, können Sie die oben erläuterten Bindungsformulare verschachteln:
(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]
Reststrukturierung in eine Sequenz
Nehmen wir an, Sie haben einen Vektor wie folgt:
(def my-vec [1 2 3 4 5 6])
Sie möchten die ersten 3 Elemente extrahieren und die restlichen Elemente als Sequenz abrufen. Dies kann wie folgt durchgeführt werden:
(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)
Vernetzung verschachtelter Vektoren
Sie können verschachtelte Vektoren zerstören:
(def my-vec [[1 2] [3 4]])
(let [[[a b][c d]] my-vec]
(println a b c d))
;; 1 2 3 4
Zerstörung einer Karte mit Standardwerten
Manchmal möchten Sie den Schlüssel unter einer Karte zerstören, der möglicherweise nicht in der Karte vorhanden ist. Sie möchten jedoch einen Standardwert für den zerstörten Wert. Das kannst du so machen:
(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
Zerstörung params eines fn
Destructurling funktioniert an vielen Stellen sowie in der Param-Liste eines Fn:
(defn my-func [[_ a b]] (+ a b)) (my-func [1 2 3]) ;= 5 (my-func (range 5)) ;= 3
Die Destrukturierung funktioniert auch für das Konstrukt & rest
in der param-Liste:
(defn my-func2 [& [_ a b]] (+ a b)) (my-func2 1 2 3) ;= 5 (apply my-func2 (range 5)) ;= 3
Den Rest einer Sequenz in eine Karte konvertieren
Durch die Zerstörung können Sie eine Sequenz auch als Karte interpretieren:
(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
Es ist nützlich, um Funktionen mit benannten Parametern zu definieren :
(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
Überblick
Bei der Destrukturierung können Sie Daten aus verschiedenen Objekten in verschiedene Variablen extrahieren. In jedem folgenden Beispiel wird jeder Variablen eine eigene Zeichenfolge zugewiesen ( a
= "a"
, b = "b"
, & c.)
Art | Beispiel | Wert der data / Kommentar |
---|---|---|
vec | (let [[abc] data ...) | ["a" "b" "c"] |
verschachteltes 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 ...) | Wenn Variablen nach den Schlüsseln benannt werden. |
Tipps:
- Standardwerte können angegeben werden mit
:or
, andernfalls ist der Standardwertnil
- Verwenden Sie
& Ruhe
ein speichernseq
aller zusätzlichen Werte inrest
, sonst werden die zusätzlichen Werte werden ignoriert - Eine übliche und nützliche Verwendung der Destrukturierung ist für Funktionsparameter
- Sie können unerwünschte Teile einer Wegwerfvariablen zuordnen (herkömmlicherweise:
_
).
Zerstörung und Bindung an den Namen der Schlüssel
Bei der Zerstörung von Karten möchten Sie manchmal die zerstörten Werte an ihren jeweiligen Schlüsselnamen binden. Abhängig von der Granularität der Datenstruktur kann die Verwendung des Standard- Destrukturierungsschemas etwas ausführlich sein .
Nehmen wir an, wir haben einen kartenbasierten Datensatz wie folgt:
(def john {:lastname "McCarthy" :firstname "John" :country "USA"})
Wir würden es normalerweise so zerstören:
(let [{lastname :lastname firstname :firstname country :country} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
Hier ist die Datenstruktur mit nur 3 Slots ( Vorname, Nachname, Land ) recht einfach. Stellen Sie sich jedoch vor, wie umständlich es wäre, wenn wir alle Schlüsselnamen zweimal wiederholen müssten , um eine detailliertere Datenstruktur zu erhalten (mit weit mehr Slots als nur 3). .
Stattdessen wird ein besserer Weg , dies zu handhaben ist durch die Verwendung :keys
(da unsere Schlüssel sind hier Schlüsselwörter) und die Schlüsselnamen der Auswahl wir so gern binden möchten:
(let [{:keys [firstname lastname country]} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
Die gleiche intuitive Logik gilt für andere Schlüsseltypen wie Symbole (using :syms
) und einfache alte Zeichenfolgen (using :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"
Den ursprünglichen Argumentwert zerstören und benennen
(defn print-some-items
[[a b :as xs]]
(println a)
(println b)
(println xs))
(print-some-items [2 3])
Dieses Beispiel druckt die Ausgabe
2
3
[2 3]
Das Argument wird zerstört und die Punkte 2
und 3
werden den Symbolen a
und b
. Das ursprüngliche Argument, der gesamte Vektor [2 3]
, wird auch dem Symbol xs
zugewiesen.