Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion Clojure-从循环内的向量中删除项_Recursion_Vector_Clojure_Functional Programming - Fatal编程技术网

Recursion Clojure-从循环内的向量中删除项

Recursion Clojure-从循环内的向量中删除项,recursion,vector,clojure,functional-programming,Recursion,Vector,Clojure,Functional Programming,我刚开始学习Clojure和函数式编程,在尝试实现以下任务时遇到了困难: 我有一个像这样的向量向量[[ab][ac][bc][cd][db]]。我需要遍历它,删除第二列中出现的项目,这些项目已经出现在第二列中。例如,项[bc]和[db](因为c和b都已出现在第二列中)。我设法得到了一个一次删除一个项的函数,但是我需要遍历每个项的向量来检查和删除这些项。我怎样才能做到这一点?我曾想过使用递归来实现这一点,但每次尝试都以失败告终对不起,如果这是一个无关紧要的问题,但我一直坚持着这一点 例如 输入:

我刚开始学习Clojure和函数式编程,在尝试实现以下任务时遇到了困难:

我有一个像这样的向量向量[[ab][ac][bc][cd][db]]。我需要遍历它,删除第二列中出现的项目,这些项目已经出现在第二列中。例如,项[bc]和[db](因为c和b都已出现在第二列中)。我设法得到了一个一次删除一个项的函数,但是我需要遍历每个项的向量来检查和删除这些项。我怎样才能做到这一点?我曾想过使用递归来实现这一点,但每次尝试都以失败告终对不起,如果这是一个无关紧要的问题,但我一直坚持着这一点

例如

输入: [a b][a c][b c][c d][a d][b e]]

输出(预期): [a b][a c][c d][b e]]

删除的项目: [b c][a d]]

(defn find-invalid [collection-data item-to-check]
    (subvec (vec (filter #(= (second %) item-to-check) collection-data)) 1))

(defn find-invalid [collection-data item-to-check]
    (subvec (vec (filter #(= (second %) item-to-check) collection-data)) 1))
如您所见,c和d已经分别出现在前面的项目[AC]和[CD]上,因此我必须删除项目[BC]和[AD]

到目前为止,我有以下代码

此函数返回要删除的项的向量。在我们的场景中,它返回向量[[bc][ad]]

(defn find-invalid [collection-data item-to-check]
    (subvec (vec (filter #(= (second %) item-to-check) collection-data)) 1))

(defn find-invalid [collection-data item-to-check]
    (subvec (vec (filter #(= (second %) item-to-check) collection-data)) 1))
另一个函数通过项的给定索引从原始向量中一次删除一个项

(defn remove-invalid [collection-data item-position]
    (vec (concat (subvec collection-data 0 item-position) (subvec collection-data (inc item-position)))))
最后一个函数就是我用来测试这个逻辑的

(defn remove-invalid [original-collection ]
    (dorun (for [item original-collection]
       [
        (dorun (for [invalid-item (find-invalid original-collection (second item))]
                 [
                  (cond (> (count invalid-item) 0)
                        (println (remove-invalid original-collection (.indexOf original-collection invalid-item)))
                        )
                  ]))
        ])))
我认为递归可以解决我的问题,但我希望能得到任何帮助:)


提前感谢。

如果我正确理解了您的问题,这应该可以做到:

(defn clear [v]
  (loop [v v existing #{} acc []]
    (if (empty? v)
      acc
      (recur (rest v)
             (conj existing (second (first v)))
             (if (some existing [(ffirst v)]) acc (conj acc (first v)))))))
使用循环/重现解决。如果我有时间的话,我会看看是否可以使用reduce之类的函数,或者任何合适的函数


此过滤器:
[[“a”b”][“a”c”][“b”c”][“c”d”][“d”b”]
[[“a”b”][“a”c”]

实现此功能的一种方法是使用:


我们希望跟踪到目前为止建立的结果(
result
)以及之前在第二列中找到的项目集(
previous
)。对于每个新项目
[ab]
,我们检查
之前的
是否包含第二个项目
b
。如果有,我们不会向
结果添加任何内容。否则,我们将新项目
[ab]
连接到
结果的末尾。我们还
将第二项
b
合并到
之前的
中。由于
previous
是一个集合,如果
previous
已包含
b
,则该集合不会起任何作用。最后,在
reduce
完成后,我们从结果中获取第一个
项,它代表我们的最终答案。

以下内容类似于,但使用
:as
子句来避免重新构建内容:

(defn filtered [stuff]
  (second
   (reduce
    (fn [[seconds ans :as sec-ans] [x y :as xy]]
      (if (seconds y)
        sec-ans
        [(conj seconds y) (conj ans xy)]))
    [#{} []]
    stuff)))
比如说,

(filtered '[[a b] [a c] [b c] [c d] [d b]])
;[[a b] [a c] [c d]]

如果您可以像示例中那样依赖于重复项是连续的,请使用

(->> '[[a b] [a c] [b c] [c d] [a d] [b e]]
     (partition-by second)
     (map first))
;-> ([a b] [a c] [c d] [b e])
否则,在Clojures传感器的基础上实现一个<代码>由<代码>区分的传感器

(sequence (distinct-by second)
          '[[a b] [a c] [b c] [c d] [a d] [b e]])

;-> ([a b] [a c] [c d] [b e])
实施

(defn distinct-by [f]
   (fn [rf]
     (let [seen (volatile! #{})]
       (fn
         ([] (rf))
         ([result] (rf result))
         ([result input]
          (let [vinput (f input)] ; virtual input as seen through f
            (if (contains? @seen vinput)
              result
              (do (vswap! seen conj vinput)
                  (rf result input)))))))))
只是为了好玩: 这些选项不保留结果的顺序,但如果您同意的话,它们非常具有表现力(重复项可以是任意顺序,不同于上面的
分区方式
):

一种是根据第二个值对所有内容进行分组,并从每个val中获取第一项:

(map (comp first val)
     (group-by second '[[a b] [a c] [b c] [c d] [a d] [b e]]))

;; => ([a b] [a c] [c d] [b e])
还有一种很好的方法,使用排序集:

(into (sorted-set-by #(compare (second %1) (second %2)))
      '[[a b] [a c] [b c] [c d] [a d] [b e]])
;; => #{[a b] [a c] [c d] [b e]}
还有一个,也是不遵守秩序的:

(vals (into {} (map (juxt second identity)
                    (rseq '[[a b] [a c] [b c] [c d] [a d] [b e]]))))
;; => ([b e] [c d] [a c] [a b])
但是是的,循环/重现总是更快,我想:

(defn remove-dupes [v]
  (loop [[[_ i2 :as pair] & xs :as v] v present #{} res []]
    (cond (empty? v) res
          (present i2) (recur xs present res)
          :else (recur xs (conj present i2) (conj res pair)))))

好问题。我相信clojure专业人士会来解围=]