需要一个类似于disj的功能,但需要一个clojure中的列表.它总体上可能吗?

dan*_*kas 3 clojure

我需要遍历一个列表并对每个元素和除该元素之外的元素进行一些计算.例如,有一个名单(1 2 3 1),我需要对(1) (2 3 1),(2) (1 3 1),(3) (1 2 1)(1) (2 3 1).

Jan*_*Jan 5

(...)包含除该元素之外的每个元素和元素.

每个元素听起来像一个map.排除该元素听起来像一个filter.让我们从后者开始吧.

user=> (filter #(not= % 1) '(1 2 3))
(2 3)
Run Code Online (Sandbox Code Playgroud)

大.现在让我们尝试将其映射到所有元素上.

user=> (let [coll '(1 2 3)] (map (fn [elem] (filter #(not= % elem) coll)) coll))
((2 3) (1 3) (1 2))
Run Code Online (Sandbox Code Playgroud)

创建实际对是留给读者的练习.提示:修改使用的闭包map.

请记住,上面建议的解决方案应该适用于短列表,但它的复杂度为O(n²).另一个问题是没有正确处理带有重复项的集合.

让我们采取递归方法.我们将基于loop和的递归recur.

(defn pairs [coll]
  (loop [ahead coll behind [] answer []]
    (if (empty? ahead)
      answer
      (let [[current & remaining] ahead]
        (recur remaining
               (conj behind current)
               (conj answer [(list current)
                             (concat behind remaining)]))))))
Run Code Online (Sandbox Code Playgroud)

一个简单的例子:

user=> (pairs '(1 2 3))
[[(1) (2 3)] [(2) (1 3)] [(3) (1 2)]]
Run Code Online (Sandbox Code Playgroud)

带有重复的向量:

user=> (pairs [1 5 6 5])
[[(1) (5 6 5)] [(5) (1 6 5)] [(6) (1 5 5)] [(5) (1 5 6)]]
Run Code Online (Sandbox Code Playgroud)


sku*_*uro 5

似乎是一份工作以获得列表理解:

(defn gimme-pairs [coll]
  (for [x coll]
    [(list x) (remove #{x} coll)]))

user=> (gimme-pairs [1 2 3])
([(1) (2 3)] [(2) (1 3)] [(3) (1 2)])
Run Code Online (Sandbox Code Playgroud)

我实际上会跳过为单个元素创建一个列表,这将使代码更容易:

(defn gimme-pairs [coll]
  (for [x coll]
    [x (remove #{x} coll)]))

user=> (gimme-pairs [1 2 3])
([1 (2 3)] [2 (1 3)] [3 (1 2)])
Run Code Online (Sandbox Code Playgroud)

如果您需要保留重复项,则可以使用索引集合:

(defn gimme-pairs [coll]
  (let [indexed (map-indexed vector coll)
        remove-index (partial map second)]
    (for [[i x] indexed]
      [x (remove-index (remove #{[i x]} indexed))])))

user=> (gimme-pairs [1 2 3 1])
([1 (2 3 1)] [2 (1 3 1)] [3 (1 2 1)] [1 (1 2 3)])
Run Code Online (Sandbox Code Playgroud)