clojure
Sammlungen und Sequenzen
Suche…
Syntax
-
'()
→()
-
'(1 2 3 4 5)
→(1 2 3 4 5)
-
'(1 foo 2 bar 3)
→(1 'foo 2 'bar 3)
-
(
list
1 2 3 4 5)
→(1 2 3 4 5)
-
(
list*
[1 2 3 4 5])
→(1 2 3 4 5)
-
[]
→[]
-
[1 2 3 4 5]
→[1 2 3 4 5]
-
(
vector
1 2 3 4 5)
→[1 2 3 4 5]
-
(
vec
'(1 2 3 4 5))
→[1 2 3 4 5]
-
{}
=>{}
-
{:keyA 1 :keyB 2}
→{:keyA 1 :keyB 2}
-
{:keyA 1, :keyB 2}
→{:keyA 1 :keyB 2}
-
(
hash-map
:keyA 1 :keyB 2)
→{:keyA 1 :keyB 2}
-
(
sorted-map
5 "five" 1 "one")
→{1 "one" 5 "five"}
(Einträge werden nach Schlüssel sortiert, wenn sie als Sequenz verwendet werden) -
#{}
→#{}
-
#{1 2 3 4 5}
→#{4 3 2 5 1}
(ungeordnet) -
(
hash-set
1 2 3 4 5)
→#{2 5 4 1 3}
(ungeordnet) -
(
sorted-set
2 5 4 3 1)
→#{1 2 3 4 5}
Sammlungen
Alle integrierten Clojure-Kollektionen sind unveränderlich und heterogen, haben wörtliche Syntax und unterstützen die Funktionen conj
, count
und seq
.
-
conj
gibt eine neue Sammlung zurück, die einer vorhandenen Sammlung mit einem hinzugefügten Element entspricht, entweder in "konstanter" oder logarithmischer Zeit. Was genau das bedeutet, hängt von der Sammlung ab. -
count
gibt die Anzahl der Elemente in einer Sammlung in konstanter Zeit zurück. -
seq
gibt für eine leere Sammlung oder eine Folge von Elementen für eine nicht leere Sammlung in konstanter Zeitnil
zurück.
Listen
Eine Liste ist in Klammern angegeben:
()
;;=> ()
Eine Clojure-Liste ist eine einzeln verknüpfte Liste . conj
"verbindet" ein neues Element mit der effizientesten Stelle der Sammlung. Bei Listen ist dies am Anfang:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
Im Gegensatz zu anderen Sammlungen werden nicht leere Listen bei der Auswertung als Aufrufe von speziellen Formularen, Makros oder Funktionen ausgewertet. Während also (:foo)
die wörtliche Darstellung der Liste enthalten :foo
als einziges Element, Bewertung (:foo)
in einem REPL bewirkt eine IllegalArgumentException
geworfen werden , weil ein Schlüsselwort nicht als aufgerufen werden kann nullary Funktion .
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
Um zu verhindern, dass Clojure eine nicht leere Liste auswertet, können Sie diese quote
:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
Leider werden die Elemente nicht ausgewertet:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Aus diesem Grund sollten Sie in der Regel verwenden list
, eine variadische Funktion , die alle ihre Argumente und verwendet diese Ergebnisse zu konstruieren , um eine Liste auswertet:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
gibt die Anzahl der Elemente in konstanter Zeit zurück:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
Sie können anhand der list?
testen, ob etwas eine list?
Prädikat:
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
Sie können das erste Element einer Liste mit peek
:
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
Sie können mit pop
eine neue Liste ohne das erste Element erhalten:
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
Beachten Sie , wenn Sie versuchen, pop
eine leere Liste, erhalten Sie eine bekommen IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Schließlich sind alle Listen Sequenzen. Sie können also alles mit einer Liste machen, die Sie mit jeder anderen Sequenz tun können. Mit Ausnahme der leeren Liste gibt der Aufruf von seq
in einer Liste genau dasselbe Objekt zurück:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true
Sequenzen
Eine Sequenz ähnelt einer Liste: Es ist ein unveränderliches Objekt, das Ihnen in konstanter Zeit sein first
Element oder den rest
seiner Elemente geben kann. Sie können auch cons
truct eine neue Sequenz aus einer bestehenden Sequenz und ein Element am Anfang zu bleiben.
Sie können mit dem seq?
testen, ob etwas eine Sequenz ist seq?
Prädikat:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
Wie Sie bereits wissen, sind Listen Sequenzen:
(seq? ())
;;=> true
(seq? '(:foo :bar))
;;=> true
Alles, was Sie erhalten, wenn Sie seq
oder rseq
oder keys
oder vals
einer nicht leeren Sammlung aufrufen, ist ebenfalls eine Sequenz:
(seq? (seq ()))
;;=> false
(seq? (seq '(:foo :bar)))
;;=> true
(seq? (seq []))
;;=> false
(seq? (seq [:foo :bar]))
;;=> true
(seq? (rseq []))
;;=> false
(seq? (rseq [:foo :bar]))
;;=> true
(seq? (seq {}))
;;=> false
(seq? (seq {:foo :bar :baz :qux}))
;;=> true
(seq? (keys {}))
;;=> false
(seq? (keys {:foo :bar :baz :qux}))
;;=> true
(seq? (vals {}))
;;=> false
(seq? (vals {:foo :bar :baz :qux}))
;;=> true
(seq? (seq #{}))
;;=> false
(seq? (seq #{:foo :bar}))
;;=> true
Denken Sie daran, dass alle Listen Sequenzen sind, aber nicht alle Sequenzen Listen sind. Während Listen peek
und pop
und count
in konstanter Zeit unterstützen, muss eine Sequenz im Allgemeinen keine dieser Funktionen unterstützen. Wenn Sie versuchen, peek
oder pop
in einer Sequenz aufzurufen, die nicht auch die Stack-Schnittstelle von Clojure unterstützt, erhalten Sie eine ClassCastException
:
(peek (seq [:foo :bar]))
;; java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to clojure.lang.IPersistentStack
(pop (seq [:foo :bar]))
;; java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to clojure.lang.IPersistentStack
(peek (seq #{:foo :bar}))
;; java.lang.ClassCastException: clojure.lang.APersistentMap$KeySeq cannot be cast to clojure.lang.IPersistentStack
(pop (seq #{:foo :bar}))
;; java.lang.ClassCastException: clojure.lang.APersistentMap$KeySeq cannot be cast to clojure.lang.IPersistentStack
(peek (seq {:foo :bar :baz :qux}))
;; java.lang.ClassCastException: clojure.lang.PersistentArrayMap$Seq cannot be cast to clojure.lang.IPersistentStack
(pop (seq {:foo :bar :baz :qux}))
;; java.lang.ClassCastException: clojure.lang.PersistentArrayMap$Seq cannot be cast to clojure.lang.IPersistentStack
Wenn Sie rufen Sie count
auf eine Sequenz, die nicht implementieren count
in konstanter Zeit, werden Sie nicht einen Fehler; Stattdessen durchquert Clojure die gesamte Sequenz bis zum Ende und gibt dann die Anzahl der Elemente zurück, die es durchlaufen hat. Dies bedeutet, dass die count
für allgemeine Sequenzen linear und nicht konstant ist. Sie können testen , ob etwas konstante Zeit unterstützt count
mit dem counted?
Prädikat:
(counted? '(:foo :bar))
;;=> true
(counted? (seq '(:foo :bar)))
;;=> true
(counted? [:foo :bar])
;;=> true
(counted? (seq [:foo :bar]))
;;=> true
(counted? {:foo :bar :baz :qux})
;;=> true
(counted? (seq {:foo :bar :baz :qux}))
;;=> true
(counted? #{:foo :bar})
;;=> true
(counted? (seq #{:foo :bar}))
;;=> false
Wie oben erwähnt, können Sie first
das erste Element einer Sequenz abrufen. Beachten Sie, dass first
seq
zu ihrem Argument aufrufen wird, sodass es für alle "seqable" -Ergebnisse verwendet werden kann, nicht nur für tatsächliche Sequenzen:
(first nil)
;;=> nil
(first '(:foo))
;;=> :foo
(first '(:foo :bar))
;;=> :foo
(first [:foo])
;;=> :foo
(first [:foo :bar])
;;=> :foo
(first {:foo :bar})
;;=> [:foo :bar]
(first #{:foo})
;;=> :foo
Wie oben erwähnt, können Sie rest
, um eine Sequenz zu erhalten, die alle Elemente außer einer der ersten Elemente einer vorhandenen Sequenz enthält. Wie first
ruft es seq
zu seinem Argument auf. Es ruft jedoch nicht seq
auf sein Ergebnis auf! Das bedeutet, wenn Sie in einer Sequenz, die weniger als zwei Elemente enthält, rest
aufrufen, erhalten Sie back ()
anstelle von nil
:
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest '(:foo :bar))
;;=> (:bar)
(rest [:foo])
;;=> ()
(rest [:foo :bar])
;;=> (:bar)
(rest {:foo :bar})
;;=> ()
(rest #{:foo})
;;=> ()
Wenn Sie nil
zurückgeben möchten, wenn keine weiteren Elemente in einer Sequenz vorhanden sind, können Sie next
anstelle von rest
:
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Sie können die cons
Funktion verwenden, um eine neue Sequenz zu erstellen, die das erste Argument für das first
und das zweite Argument für den rest
:
(cons :foo nil)
;;=> (:foo)
(cons :foo (cons :bar nil))
;;=> (:foo :bar)
Clojure bietet eine große Sequenzbibliothek mit vielen Funktionen für den Umgang mit Sequenzen. Das Wichtigste an dieser Bibliothek ist, dass sie mit etwas "seqable" funktioniert, nicht nur mit Listen. Deshalb ist das Konzept einer Sequenz so nützlich. Das bedeutet, dass eine einzelne Funktion, wie zum Beispiel " reduce
, für jede Sammlung perfekt funktioniert:
(reduce + '(1 2 3))
;;=> 6
(reduce + [1 2 3])
;;=> 6
(reduce + #{1 2 3})
;;=> 6
Der andere Grund, warum Sequenzen nützlich sind, besteht darin, dass sie, da sie keine bestimmte Implementierung von first
und rest
erfordern, lazy-Sequenzen zulassen, deren Elemente nur bei Bedarf realisiert werden.
Bei einem Ausdruck, der eine Sequenz erzeugen würde, können Sie diesen Ausdruck in das lazy-seq
Makro einschließen, um ein Objekt zu erhalten, das sich wie eine Sequenz verhält. Der Ausdruck wird jedoch nur ausgewertet, wenn er von der Funktion seq
(at) aufgefordert wird welcher Stelle es das Ergebnis des Ausdrucks zwischenzuspeichern und nach vorn first
und rest
Anrufe an die im Cache gespeicherten Ergebnis.
Bei endlichen Sequenzen fungiert eine Lazy-Sequenz normalerweise als äquivalente eifrige Sequenz:
(seq [:foo :bar])
;;=> (:foo :bar)
(lazy-seq [:foo :bar])
;;=> (:foo :bar)
Der Unterschied wird jedoch für unendliche Sequenzen deutlich:
(defn eager-fibonacci [a b]
(cons a (eager-fibonacci b (+' a b))))
(defn lazy-fibonacci [a b]
(lazy-seq (cons a (lazy-fibonacci b (+' a b)))))
(take 10 (eager-fibonacci 0 1))
;; java.lang.StackOverflowError:
(take 10 (lazy-fibonacci 0 1))
;;=> (0 1 1 2 3 5 8 13 21 34)
Vektoren
Ein Vektor wird durch eckige Klammern angezeigt:
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
Neben der Literal-Syntax können Sie auch die vector
verwenden, um einen Vektor zu konstruieren:
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector :foo :bar)
;;=> [:foo :bar]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
Sie können mit dem vector?
testen, ob etwas ein Vektor vector?
Prädikat:
(vector? [])
;;=> true
(vector? [:foo :bar])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
conj
fügt Elemente am Ende eines Vektors hinzu:
(conj [] :foo)
;;=> [:foo]
(conj (conj [] :foo) :bar)
;;=> [:foo :bar]
(conj [] :foo :bar)
;;=> [:foo :bar]
count
gibt die Anzahl der Elemente in konstanter Zeit zurück:
(count [])
;;=> 0
(count (conj [] :foo))
;;=> 1
(count [:foo :bar])
;;=> 2
Sie können das letzte Element eines Vektors mithilfe von peek
:
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
(peek [:foo :bar])
;;=> :bar
Sie können mit pop
einen neuen Vektor ohne das letzte Element erhalten:
(pop [:foo])
;;=> []
(pop [:foo :bar])
;;=> [:foo]
Wenn Sie versuchen, einen leeren Vektor zu platzieren, erhalten Sie eine IllegalStateException
:
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
Im Gegensatz zu Listen werden Vektoren indiziert. Sie können ein Element eines Vektors über den Index in "konstanter" Zeit erhalten, indem get
:
(get [:foo :bar] 0)
;;=> :foo
(get [:foo :bar] 1)
;;=> :bar
(get [:foo :bar] -1)
;;=> nil
(get [:foo :bar] 2)
;;=> nil
Vektoren selbst sind außerdem Funktionen, die einen Index übernehmen und das Element an diesem Index zurückgeben:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Wenn Sie jedoch einen Vektor mit einem ungültigen Index aufrufen, erhalten Sie eine IndexOutOfBoundsException
anstelle von nil
:
([:foo :bar] -1)
;; java.lang.IndexOutOfBoundsException:
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
Mit assoc
können Sie einen neuen Vektor mit einem anderen Wert an einem bestimmten Index assoc
:
(assoc [:foo :bar] 0 42)
;;=> [42 :bar]
(assoc [:foo :bar] 1 42)
;;=> [:foo 42]
Wenn Sie einen Index übergeben, der der count
des Vektors entspricht, fügt Clojure das Element so hinzu, als hätten Sie conj
. Wenn Sie jedoch einen Index übergeben, der negativ oder größer als die count
, erhalten Sie eine IndexOutOfBoundsException
:
(assoc [:foo :bar] 2 42)
;;=> [:foo :bar 42]
(assoc [:foo :bar] -1 42)
;; java.lang.IndexOutOfBoundsException:
(assoc [:foo :bar] 3 42)
;; java.lang.IndexOutOfBoundsException:
Sie können eine Sequenz der Elemente in einem Vektor mithilfe von seq
:
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
(seq [:foo :bar])
;;=> (:foo :bar)
Da Vektoren indiziert sind, können Sie mit rseq
auch eine umgekehrte Reihenfolge der Elemente eines Vektors rseq
:
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
(rseq [:foo :bar])
;;=> (:bar :foo)
Beachten Sie, dass, obwohl alle Listen Sequenzen sind und Sequenzen auf dieselbe Weise wie Listen angezeigt werden, nicht alle Sequenzen Listen sind!
'(:foo :bar)
;;=> (:foo :bar)
(seq [:foo :bar])
;;=> (:foo :bar)
(list? '(:foo :bar))
;;=> true
(list? (seq [:foo :bar]))
;;=> false
(list? (rseq [:foo :bar]))
;;=> false
Sets
Wie Karten sind Sets assoziativ und ungeordnet. Im Gegensatz zu Karten, die Zuordnungen von Schlüsseln zu Werten enthalten, wird im Wesentlichen eine Zuordnung von Schlüsseln zu sich selbst vorgenommen.
Ein Satz wird durch geschweifte Klammern bezeichnet, denen ein Oktothorpe vorangeht:
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Wie bei Karten spielt die Reihenfolge, in der Elemente in einem Literalsatz angezeigt werden, keine Rolle:
(= #{:foo :bar} #{:bar :foo})
;;=> true
Sie können mit dem set?
testen, ob etwas ein set?
Prädikat:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? #{:foo :bar})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
Sie können testen, ob eine Karte ein bestimmtes Element in "konstanter" Zeit contains?
indem Sie das contains?
Prädikat:
(contains? #{} :foo)
;;=> false
(contains? #{:foo} :foo)
;;=> true
(contains? #{:foo} :bar)
;;=> false
(contains? #{} nil)
;;=> false
(contains? #{nil} nil)
;;=> true
Außerdem sind Mengen selbst Funktionen, die ein Element annehmen und dieses Element zurückgeben, wenn es in der Menge vorhanden ist, oder nil
wenn es nicht der nil
ist:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Sie können mit conj
einen Satz erhalten, der alle Elemente eines vorhandenen Satzes sowie ein weiteres Element enthält:
(conj #{} :foo)
;;=> #{:foo}
(conj (conj #{} :foo) :bar)
;;=> #{:bar :foo}
(conj #{:foo} :foo)
;;=> #{:foo}
Sie können disj
, um einen Satz disj
, der alle Elemente eines vorhandenen Satzes enthält, abzüglich eines Elements:
(disj #{} :foo)
;;=> #{}
(disj #{:foo} :foo)
;;=> #{}
(disj #{:foo} :bar)
;;=> #{:foo}
(disj #{:foo :bar} :foo)
;;=> #{:bar}
(disj #{:foo :bar} :bar)
;;=> #{:foo}
count
gibt die Anzahl der Elemente in konstanter Zeit zurück:
(count #{})
;;=> 0
(count (conj #{} :foo))
;;=> 1
(count #{:foo :bar})
;;=> 2
Sie können eine Folge aller Elemente in einem Satz mit seq
:
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
(seq #{:foo :bar})
;;=> (:bar :foo)
Karten
Im Gegensatz zu der Liste, die eine sequentielle Datenstruktur ist, und dem Vektor, der sowohl sequentiell als auch assoziativ ist, ist die Karte ausschließlich eine assoziative Datenstruktur. Eine Map besteht aus einem Satz von Mappings von Schlüsseln zu Werten. Da alle Schlüssel eindeutig sind, unterstützen Karten die Suche nach "konstanten" Zeiten von Schlüsseln zu Werten.
Eine Karte wird durch geschweifte Klammern gekennzeichnet:
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
{:foo :bar :baz :qux}
;;=> {:foo :bar, :baz :qux}
Jedes Paar von zwei Elementen ist ein Schlüsselwertpaar. So hat beispielsweise die erste Karte oben keine Zuordnungen. Die zweite hat eine Zuordnung, vom Schlüssel :foo
bis zum Wert :bar
. Die dritte hat zwei Zuordnungen, eine vom Schlüssel :foo
zum Wert :bar
und eine vom Schlüssel :baz
zum Wert :qux
. Karten sind von Haus aus ungeordnet, daher spielt es keine Rolle, in welcher Reihenfolge die Zuordnungen angezeigt werden:
(= {:foo :bar :baz :qux}
{:baz :qux :foo :bar})
;;=> true
Sie können mit der map?
testen, ob etwas eine map?
Prädikat:
(map? {})
;;=> true
(map? {:foo :bar})
;;=> true
(map? {:foo :bar :baz :qux})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
Sie können testen, ob eine Karte einen bestimmten Schlüssel in "konstanter" Zeit contains?
indem Sie das contains?
Prädikat:
(contains? {:foo :bar :baz :qux} 42)
;;=> false
(contains? {:foo :bar :baz :qux} :foo)
;;=> true
(contains? {:foo :bar :baz :qux} :bar)
;;=> false
(contains? {:foo :bar :baz :qux} :baz)
;;=> true
(contains? {:foo :bar :baz :qux} :qux)
;;=> false
(contains? {:foo nil} :foo)
;;=> true
(contains? {:foo nil} :bar)
;;=> false
Sie können den mit einem Schlüssel verknüpften Wert mit get
:
(get {:foo :bar :baz :qux} 42)
;;=> nil
(get {:foo :bar :baz :qux} :foo)
;;=> :bar
(get {:foo :bar :baz :qux} :bar)
;;=> nil
(get {:foo :bar :baz :qux} :baz)
;;=> :qux
(get {:foo :bar :baz :qux} :qux)
;;=> nil
(get {:foo nil} :foo)
;;=> nil
(get {:foo nil} :bar)
;;=> nil
Darüber hinaus sind Maps selbst Funktionen, die einen Schlüssel annehmen und den mit diesem Schlüssel verknüpften Wert zurückgeben:
({:foo :bar :baz :qux} 42)
;;=> nil
({:foo :bar :baz :qux} :foo)
;;=> :bar
({:foo :bar :baz :qux} :bar)
;;=> nil
({:foo :bar :baz :qux} :baz)
;;=> :qux
({:foo :bar :baz :qux} :qux)
;;=> nil
({:foo nil} :foo)
;;=> nil
({:foo nil} :bar)
;;=> nil
Sie können einen vollständigen Karteneintrag (Schlüssel und Wert zusammen) als Vektor mit zwei Elementen erhalten, indem Sie find
:
(find {:foo :bar :baz :qux} 42)
;;=> nil
(find {:foo :bar :baz :qux} :foo)
;;=> [:foo :bar]
(find {:foo :bar :baz :qux} :bar)
;;=> nil
(find {:foo :bar :baz :qux} :baz)
;;=> [:baz :qux]
(find {:foo :bar :baz :qux} :qux)
;;=> nil
(find {:foo nil} :foo)
;;=> [:foo nil]
(find {:foo nil} :bar)
;;=> nil
Sie können den Schlüssel oder Wert aus einer MapEintrag extrahieren mit key
oder val
jeweils:
(key (find {:foo :bar} :foo))
;;=> :foo
(val (find {:foo :bar} :foo))
;;=> :bar
Obwohl alle Clojure-Karteneinträge Vektoren sind, sind nicht alle Vektoren Karteneinträge. Wenn Sie versuchen, key
oder val
bei einem ClassCastException
Eintrag ClassCastException
, der kein Map-Eintrag ist, wird eine ClassCastException
:
(key [:foo :bar])
;; java.lang.ClassCastException:
(val [:foo :bar])
;; java.lang.ClassCastException:
Sie können mit dem map-entry?
testen, ob etwas ein Karteneintrag ist map-entry?
Prädikat:
(map-entry? (find {:foo :bar} :foo))
;;=> true
(map-entry? [:foo :bar])
;;=> false
Sie können assoc
, um eine Karte zu erhalten, die alle die gleichen Schlüsselwertpaare wie eine vorhandene Karte enthält, wobei eine Zuordnung hinzugefügt oder geändert wurde:
(assoc {} :foo :bar)
;;=> {:foo :bar}
(assoc (assoc {} :foo :bar) :baz :qux)
;;=> {:foo :bar, :baz :qux}
(assoc {:baz :qux} :foo :bar)
;;=> {:baz :qux, :foo :bar}
(assoc {:foo :bar :baz :qux} :foo 42)
;;=> {:foo 42, :baz :qux}
(assoc {:foo :bar :baz :qux} :baz 42)
;;=> {:foo :bar, :baz 42}
Sie können dissoc
, um eine Karte zu erhalten, die alle die gleichen Schlüsselwertpaare wie eine vorhandene Karte enthält, wobei möglicherweise eine Zuordnung entfernt wurde:
(dissoc {:foo :bar :baz :qux} 42)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo :bar :baz :qux} :foo)
;;=> {:baz :qux}
(dissoc {:foo :bar :baz :qux} :bar)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo :bar :baz :qux} :baz)
;;=> {:foo :bar}
(dissoc {:foo :bar :baz :qux} :qux)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo nil} :foo)
;;=> {}
count
gibt die Anzahl der Mappings in konstanter Zeit zurück:
(count {})
;;=> 0
(count (assoc {} :foo :bar))
;;=> 1
(count {:foo :bar :baz :qux})
;;=> 2
Sie können eine Reihenfolge aller Einträge in einer Karte mit seq
:
(seq {})
;;=> nil
(seq {:foo :bar})
;;=> ([:foo :bar])
(seq {:foo :bar :baz :qux})
;;=> ([:foo :bar] [:baz :qux])
Auch hier sind Karten nicht geordnet, daher ist die Reihenfolge der Elemente in einer Reihenfolge, die Sie erhalten, wenn Sie seq
auf einer Karte aufrufen, undefiniert.
Sie können die Tasten eine Sequenz von nur bekommen oder einfach nur die Werte in einer Karte mithilfe von keys
oder vals
jeweils:
(keys {})
;;=> nil
(keys {:foo :bar})
;;=> (:foo)
(keys {:foo :bar :baz :qux})
;;=> (:foo :baz)
(vals {})
;;=> nil
(vals {:foo :bar})
;;=> (:bar)
(vals {:foo :bar :baz :qux})
;;=> (:bar :qux)
Clojure 1.9 fügt eine Literal-Syntax hinzu, um eine Karte, in der die Schlüssel denselben Namespace verwenden, übersichtlicher darzustellen. Beachten Sie, dass die Map in beiden Fällen identisch ist (die Map "kennt" den Standard-Namespace nicht). Dies ist lediglich eine Vereinfachung der Syntax.
;; typical map syntax
(def p {:person/first"Darth" :person/last "Vader" :person/email "[email protected]"})
;; namespace map literal syntax
(def p #:person{:first "Darth" :last "Vader" :email "[email protected]"})