在Clojure中使用reduce/map时尝试跟踪迭代是否是一种不好的做法?

在Clojure中使用reduce/map时尝试跟踪迭代是否是一种不好的做法?,clojure,Clojure,因此,作为Clojure和函数式编程的新手,我有时(引用一本书)“感觉你最喜欢的工具被拿走了”。为了更好地掌握这些东西,我正在处理字符串操作问题 因此,了解函数范式是关于递归(以及其他事情)的,我一直在使用尾部递归函数来完成我通常使用循环所做的事情,然后尝试使用map或reduce来实现。对于那些更有经验的人来说,这听起来像是一件明智的事情吗 我开始感到沮丧,因为我遇到了一些问题,在迭代字符串时需要跟踪每个字符的索引,但事实证明这很困难,因为reduce和map感觉“孤立”。当字符串被减少时,我

因此,作为Clojure和函数式编程的新手,我有时(引用一本书)“感觉你最喜欢的工具被拿走了”。为了更好地掌握这些东西,我正在处理字符串操作问题

因此,了解函数范式是关于递归(以及其他事情)的,我一直在使用尾部递归函数来完成我通常使用循环所做的事情,然后尝试使用map或reduce来实现。对于那些更有经验的人来说,这听起来像是一件明智的事情吗

我开始感到沮丧,因为我遇到了一些问题,在迭代字符串时需要跟踪每个字符的索引,但事实证明这很困难,因为reduce和map感觉“孤立”。当字符串被减少时,我不能增加值

有没有什么我错过了;正是这个函数。。或者,这种特定情况是否可以不使用这些核心功能来实现?还是我现在的做法是错误的,不起作用,这就是我被卡住的原因

我举了一个例子:

此函数获取五个单独的字符串,然后使用
reduce
,构建一个向量,其中包含每个字符串中char位置处的所有字符。如何更改此代码,以便在传递每个字符串后,char at(在匿名函数中)递增?这就是我所说的感觉“孤立”的意思,我不知道如何摆脱它

(defn new-string-from-five
  "This function takes a character at position char-at from each of the strings to make a new vector"
  [five-strings char-at]
  (reduce (fn [result string]
            (conj result (get-char-at string char-at)))
    []
    five-strings))
旧的: “abc”“def”“ghi”“jkl”“mno”->[a d g j m](始终取自索引0)
已修改
“abc”“def”“ghi”“jkl”“mno”>[ae j n](索引会递增并循环)

我认为编写字符串manip函数来让您的头脑了解事情并没有什么疯狂之处,尽管这肯定不是唯一的方法。我个人认为clojure适合勇敢和真诚的人,而clojure人在学习clojure时最有帮助

关于您的问题,最常见的做法可能是使用
map index

(user=> (map-indexed vector [9 9 9])
([0 9] [1 9] [2 9])
以你为例

(defn new-string-from-five
  "This function takes a character at position char-at from each of the strings to make a new vector"
  [five-strings char-at]
  (reduce (fn [result [string-idx string]]
            (conj result (get-char-at string (+ string-idx char-at))))
    []
    (map-indexed vector five-strings)))
但我如何建立地图索引?嗯

不懒惰地:

(defn map-indexed' [f coll]
  (loop [idx 0
         res []
         rest-coll coll]
    (if (empty? rest-coll)
      res
      (recur (inc idx) (conj res (f idx (first rest-coll))) (rest rest-coll)))))
懒散地(建议不要试图理解这一点):


您可以使用
缩减

(从五个字符串中定义新字符串
[五条线]
(->五根弦
(减少
(fn[[res i]字符串]
[(在字符串i处获取字符)(inc i)])
[nil 0])
休息
(mapv优先)
但在这种情况下,我认为
map
mapv
map-indexed
更干净。例如

(地图索引)
(fn[i s](在s i处获取字符))
[“abc”“def”“ghi”“jkl”“mno”])
(reduce(fn[acc x](conj-acc(f x)))[]coll)
通常最好写成
(map f coll)
。因此,您的第一个示例是
(map(fn[[string idx string]]…)(map indexed vector five strings))
…在这一点上,您可以使用
map indexed
开始<代码>(映射索引(fn[string idx string]…)五个字符串)
(defn map-indexed' [f coll]
  (letfn [(map-indexed'' [idx f coll]
            (if (empty? coll)
              '()
              (lazy-seq (conj (map-indexed'' (inc idx) f (rest coll)) (f idx (first coll))))))]
    (map-indexed'' 0 f coll)))