List Clojure-对列表列表中的每个项目进行操作

List Clojure-对列表列表中的每个项目进行操作,list,clojure,functional-programming,return-value,List,Clojure,Functional Programming,Return Value,我正在做我在Clojure的第一个功能程序。我在计算如何单步遍历列表中的每一项、列表中的每一项并在保留返回值的同时对其进行操作时遇到了一些问题。我确信这个问题源于我对Clojure和函数式编程的不熟悉,我希望有人能解释执行以下操作的最佳方法: psuedo-code algorithm: for each lst in list for each item in lst return_values.append = do_something(item) (vec-deep-w

我正在做我在Clojure的第一个功能程序。我在计算如何单步遍历列表中的每一项、列表中的每一项并在保留返回值的同时对其进行操作时遇到了一些问题。我确信这个问题源于我对Clojure和函数式编程的不熟悉,我希望有人能解释执行以下操作的最佳方法:

psuedo-code algorithm:
for each lst in list
   for each item in lst
      return_values.append = do_something(item)
(vec-deep-walk (partial + 1) [1 [2 3] 4 [5 [6 7]]])
我首先尝试嵌套两个
doseq
函数,然后调用我的
dou\u something
函数,该函数可以对项目调用函数,但没有保存返回值。然后,我尝试将
for
cons
添加到空列表中,但无法获取
for
之外的返回值

是否有可能/更可取的做法是先将清单分解?我还能得到一个返回值列表吗

最后,我希望结果是返回值列表的列表,以匹配列表的输入列表。
如果有人能解释在Clojure中执行此操作的最佳方法及其原因,我们将不胜感激。

如果您有一个嵌套很深的列表,并且希望保留其结构,但要转换值,则可以使用
Clojure.walk/postwall
对每个值进行操作,例如:

(def nested '(1 (2 3 (4 5)) 6))

(defn transform-values [coll f]
  (clojure.walk/postwalk #(if (not (list? %))
                            (f %)
                            %)
                         coll))

(transform-values nested inc)

=> (2 (3 4 (5 6)) 7)

当然,您可以将任何函数传递给
转换值

,这可以通过简单的递归遍历来完成。想到这一点的第一个实现是以下序列:

(defn deep-walk
  [f data]
  (map (fn [s] (if (seq? s) 
                 (deep-walk f s) 
                 (f s))) 
        data))
向量的这种微小变化:

(defn vec-deep-walk
  [f data]
  (vec (map (fn [s] (if (vector? s) 
                      (vec-deep-walk f s) 
                      (f s))) 
            data)))
只需对以下内容进行快速测试:

psuedo-code algorithm:
for each lst in list
   for each item in lst
      return_values.append = do_something(item)
(vec-deep-walk (partial + 1) [1 [2 3] 4 [5 [6 7]]])
提供以下输出:

[2 [3 4] 5 [6 [7 8]]]

walk函数采用两个参数,第一个是采用单个参数的函数。这将为数据中的每个非seq/vector元素调用,并作为第二个参数传递。结果将以与输入结构相同的嵌套结构返回。

nested
for
循环将实现以下功能:

(for [lst my-list]
  (for [item lst] (do_something item)))
它将采用嵌套列表
my list
(列表列表)并通过对每个元素应用
do\u something
将其转换为另一个嵌套列表


在clojure中,
for
已经返回了一个值列表,因此不需要自己处理。此外,由于clojure中的所有数据结构都是不可变的,因此不能通过使用
cons

将元素添加到初始空列表来实现这一点,感谢您的响应!我尝试过这个,但当我尝试用我的价值观做任何事情时,仍然得到零。我使用了一些类似于
(def my\u vals(transform values my\u coll my\u func))
的东西。我是不是把那些值弄错了?好吧,我发现其中的一些问题是我有一个序列,而不是一个列表,所以我将
list?
交换为
seq?
,现在得到了我的值,但看起来我仍然在将整个列表传递到我的函数中。我的数据被组织为
[[abc][def][gi]]
,所以它是一个包含多个列表的列表,我需要我的函数来操作
a
b
c
d
e
,等等。我可以嵌套
walk
来实现这一点吗?向量不是序号。(seq?[])=>falseI更新了代码以提供替代方案。当然,你可以在那里有一个
来支持序列、列表和向量。也可以在单个For中工作:
(对于[row my list,cell row](…)
@cfrick single
For
将生成包含所有元素的扁平列表,而不是嵌套的元素。这是真的,我认为OP想要什么——或者至少我是如何解释
return\u values.append=f(item)
@cfrick我觉得OP的问题在这里有点混乱,因为他要求一个嵌套列表,但包含伪代码示例以获得一个扁平列表。@LeonidBeschastny是的,对不起,我的伪代码是错误的。我确实希望我的结果在一个与输入列表结构完全相同的列表中。您说
for
已经返回了一个值列表,但是数据结构是不可变的,所以它不能进行适当的更改(用函数的结果替换输入的每个值),是吗?那么我如何访问
for
的返回值呢?如果嵌套是一致的,并且是一级深的,Leonid的for解决方案将起作用。在这种情况下,这无疑是一个更简单的解决方案。递归解决方案将在更一般的解决方案中处理嵌套结构中的任何复杂程度。