[英]How to pair items from a nested vector with corresponding single values in Clojure?
我正在学习Clojure,并想进一步了解序列。 我有一个现实生活中的问题,我已经简化为一个通用问题,但是我不知道它是否具有规范名称。 希望下面的例子可以清楚地说明。
假设我有两个向量src
和dst
。 src
向量中的项目本身就是向量,我需要将每个向量中的每个项目映射到dst
的相应值。
(def src [ ["a1" "a2" "a3"] ["b1" "b2"] ["c1" "c2" "c3" "c4"] ])
(def dst [ "a" "b" "c" ])
我要制作以下地图:
{ :a1 "a", :a2 "a", :a3 "a", :b1 "b", :b2 "b", :c1 "c", :c2 "c", :c3 "c", :c4 "c" }
我可以在Python中做到这一点,但是Clojure的实现方式对我来说并不明确。 对于这个问题,我可以只构造一个地图,但是我希望能够以一种通用的方式进行操作,而不仅仅是针对此实例。
在Python中,这将是:
src = [['a1', 'a2', 'a3'], ['b1', 'b2'], ['c1', 'c2', 'c3', 'c4']]
dst = ['a', 'b', 'c']
result = {}
for (s, d) in zip(src, dst):
for x in s:
result[x] = d
在Clojure中,我尝试从以下开始:
(interleave src dst)
;=> (["a1" "a2"] "a" ["b1" "b2" "b3"] "b" ["c1"] "c")
因此,我将向量展平了,但是我不知道如何遍历map键并选择值。
另外, zipmap
本身并不zipmap
我太过远:
(zipmap src (map keyword dst))
;=> {["c1"] :c, ["b1" "b2" "b3"] :b, ["a1" "a2"] :a}
;bogus result
现在,我需要翻转映射键和值,并仍然进行迭代。
我也没有成功构建for
表达式:
(for [s src] (zipmap s dst)))
;=> ({"a2" "b", "a1" "a"} {"b3" "c", "b2" "b", "b1" "a"} {"c1" "a"})
;bogus result
我正在通过将两个向量配对来解决问题,但是我似乎无法将src
向量中的向量放置到适当的位置,因此我可以简单地用dst
zipmap
每个向量。
我怀疑答案确实很明显,但是我的大脑仍无法正常工作。 也许某处有一个into {}
和/或assoc
。
有指针吗? 如果您感兴趣,我提到的现实问题是从RNA密码子到氨基酸的映射。
user> (into {}
(for [[sources, dest] (map list src dst),
source sources]
[(keyword source), dest]))
{:a2 "a", :b2 "b", :c3 "c", :a3 "a", :a1 "a", :b1 "b", :c4 "c", :c2 "c", :c1 "c"}
for
理解会创建每个源/目标对,然后使用into
从这些对填充哈希映射。
map
可能需要多个seq进行迭代,例如:
(map + [1 2 3] [4 5 6])
;; => (5 7 9)
因此,这就是将要处理的值转换为相同函数的方式,从而导致处理对["a1" "a2" "a3"]
/ "a"
等。
(map
(fn [src dst]
???)
[["a1" "a2" "a3"] ["b1" "b2"] ["c1" "c2" "c3" "c4"]]
["a" "b" "c"])
zipmap
包含一系列键(我们拥有)和一系列值(我们必须从单个值构造)。 repeat
可用于基于常量值创建无限的惰性repeat
:
(take 3 (repeat "a"))
;; => ("a" "a" "a")
和:
(zipmap ["a1" "a2" "a3"] (repeat "a"))
;; => {"a3" "a", "a2" "a", "a1" "a"}
这使原始代码如下所示:
(map
(fn [src dst]
(zipmap src (repeat dst)))
[["a1" "a2" "a3"] ["b1" "b2"] ["c1" "c2" "c3" "c4"]]
["a" "b" "c"])
;; => ({"a3" "a", "a2" "a", "a1" "a"} {"b2" "b", "b1" "b"} {"c4" "c", "c3" "c", "c2" "c", "c1" "c"})
最后,您可以使用into
将所有这些映射合并到一个映射中,从而得到最后的代码:
(into {} (map #(zipmap %1 (repeat %2)) src dst))
;; => {"a3" "a", "c2" "c", "c3" "c", "a1" "a", "b2" "b", "c4" "c", "a2" "a", "c1" "c", "b1" "b"}
(into {} (mapcat (fn [ss d] (map #(vector (keyword %) d) ss)) src dst))
;{:a3 "a", :c1 "c", :c2 "c", :b2 "b",
; :b1 "b", :c4 "c", :c3 "c", :a2 "a", :a1 "a"}
...但是我更喜欢@ noisesmith's- for
在这里更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.