development

Clojure에서 맵 키와 값을 반복하는 방법은 무엇입니까?

big-blog 2020. 12. 4. 19:42
반응형

Clojure에서 맵 키와 값을 반복하는 방법은 무엇입니까?


반복하려는 다음 맵이 있습니다.

(def db {:classname "com.mysql.jdbc.Driver" 
         :subprotocol "mysql" 
         :subname "//100.100.100.100:3306/clo" 
         :username "usr" :password "pwd"})

다음을 시도했지만 키와 값을 한 번 인쇄하는 대신 다양한 조합으로 키와 값을 반복적으로 인쇄합니다.

(doseq [k (keys db) 
        v (vals db)] 
  (println (str k " " v)))

나는 해결책을 찾았지만 Brian의 (아래 참조) 훨씬 더 논리적입니다.

(let [k (keys db) v (vals db)] 
  (do (println (apply str (interpose " " (interleave k v))))))

그것은 예상되는 행동입니다. (doseq [x ... y ...])의 모든 항목에 y대해의 모든 항목을 반복 x합니다.

대신지도 자체를 한 번 반복해야합니다. (seq some-map)맵의 각 키 / 값 쌍에 대해 하나씩 두 항목 벡터 목록을 반환합니다. (정말 clojure.lang.MapEntry이지만 2- 항목 벡터처럼 동작합니다.)

user> (seq {:foo 1 :bar 2})
([:foo 1] [:bar 2])

doseq다른 시퀀스와 마찬가지로 해당 시퀀스를 반복 할 수 있습니다. 컬렉션과 함께 작동하는 Clojure의 대부분의 함수와 마찬가지로 컬렉션을 반복하기 전에 doseq내부적 으로 컬렉션을 호출 seq합니다. 따라서 간단히 이렇게 할 수 있습니다.

user> (doseq [keyval db] (prn keyval))
[:subprotocol "mysql"]
[:username "usr"]
[:classname "com.mysql.jdbc.Driver"]
[:subname "//100.100.100.100:3306/clo"]
[:password "pwd"]

당신은 사용할 수 있습니다 keyval, 또는 firstsecond하거나 nth, 또는 get이러한 벡터에서 키와 값을 얻을 수 있습니다.

user> (doseq [keyval db] (prn (key keyval) (val keyval)))
:subprotocol "mysql"
:username "usr"
:classname "com.mysql.jdbc.Driver"
:subname "//100.100.100.100:3306/clo"
:password "pwd"

더 간결하게는 구조 분해를 사용하여 맵 항목의 각 절반을 doseq양식 내에서 사용할 수있는 일부 이름에 바인딩 할 수 있습니다 . 이것은 관용적입니다.

user> (doseq [[k v] db] (prn k v))
:subprotocol "mysql"
:username "usr"
:classname "com.mysql.jdbc.Driver"
:subname "//100.100.100.100:3306/clo"
:password "pwd"

당신은 단순히 할 수 있습니다

(map (fn [[k v]] (prn k) (prn v)) {:a 1 :b 2})

결과는 다음과 같습니다.

:a
1
:b
2

이것이 당신이 찾던 것입니까?


Brian의 답변에 대한 짧은 추가 사항 :

원래 버전은 다음과 같이 작성할 수도 있습니다.

(doseq [[k v] (map vector (keys db) (vals db))]
  (println (str k " " v)))

In this case this is obviously silly. But in general this works also for unrelated input sequences, which do not stem from the same map.


It's not totally clear if you are trying to solve something beyond just printing out values (side effects), and if that's all you're going for then I think the doseq solution above would be the most idiomatic. If you want to do some operations on the keys and values of the map and return the same type of data structure, then you should have a look at reduce-kv, for which you can find the docs for here

Like reduce, reduce-kv accepts a function, a starting value/accumulator, and some data, but in this case the data is a map instead of a sequence. The function gets passed three args: the accumulator, current key, and current value. If you do want to do some data transformation and return some data, this would seem like the right tool for the job to me.

참고URL : https://stackoverflow.com/questions/6685916/how-to-iterate-over-map-keys-and-values-in-clojure

반응형