[英]Clojure: Cycle through a collection while looping through another collection?
I have two collections x
and y
, both having different number of items. 我有两个集合x
和y
,两个都有不同的项目数。 I want to loop through x
and do something with a side-effect, while cycling through y
. 我想循环通过x
并做一些副作用,同时循环通过y
。 I don't want to repeat y
while looping through x
. 我不想在循环x
重复y
。 Both doseq
and for
repeats y
: 无论doseq
和for
重复y
:
(for [x (range 5)
y ["A" "B"]]
[x y])
This produces ([0 "A"] [0 "B"] [1 "A"] [1 "B"] [2 "A"] [2 "B"] [3 "A"] [3 "B"] [4 "A"] [4 "B"])
. 这产生([0 "A"] [0 "B"] [1 "A"] [1 "B"] [2 "A"] [2 "B"] [3 "A"] [3 "B"] [4 "A"] [4 "B"])
。
What I want is something that will produce: ([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])
. 我想要的是会产生的东西: ([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])
。
Background, I have lines from a file and core.async
channels (say 5) and I want to put each line to the next channel in my collection, something like: 背景,我有来自文件和core.async
频道的行(比如5),我想把每一行放到我的集合中的下一个频道,如:
(defn load-data
[file chans]
(with-open [rdr (io/reader file)]
(go
(doseq [l (line-seq rdr)
ch chans]
(>! ch l)))))
If you pass multiple sequences to map
it steps through each of them in lock step calling the mapped function with the value from the current position in each. 如果您传递多个序列进行map
则会在锁定步骤中逐步执行每个序列,并使用每个序列中的当前位置调用映射函数。 Stopping when one of the sequences runs out. 当其中一个序列用完时停止。
user> (map vector (range 5) (cycle ["A" "B"]))
([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])
In this case the sequence from (cycle ["A" "B"])
will keep producing As and Bs forever though map will stop consuming them when the sequence from (range 5)
ends. 在这种情况下,来自(cycle ["A" "B"])
的序列将永远产生As和Bs,尽管当(range 5)
的序列结束时,map将停止消耗它们。 each step then calls the vector function with these two arguments and adds the result to the output sequence. 然后,每一步都使用这两个参数调用vector函数,并将结果添加到输出序列中。
and for the second example using a go-loop is a fairly standard way of fanning out an input sequence: 对于第二个使用go-loop的例子是一个相当标准的扇出输入序列的方法:
user> (require '[clojure.core.async :refer [go go-loop <! <!! >!! >! chan close!]])
nil
user> (defn fanout [channels file-lines]
(go-loop [[ch & chans] (cycle channels)
[line & lines] file-lines]
(if line
(do
(>! ch line)
(recur chans lines))
(doseq [c channels]
(close! c)))))
#'user/fanout
user> (def lines ["first" "second" "third" "fourth" "fifth"])
#'user/lines
user> (def test-chans [(chan) (chan) (chan)])
#'user/test-chans
user> (fanout test-chans lines)
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@3b363fc5>
user> (map <!! test-chans)
("first" "second" "third")
user> (map <!! test-chans)
("fourth" "fifth" nil)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.