Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.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
需要一个类似于disj的函数,但用于clojure中的列表。总体上可能吗?_Clojure - Fatal编程技术网

需要一个类似于disj的函数,但用于clojure中的列表。总体上可能吗?

需要一个类似于disj的函数,但用于clojure中的列表。总体上可能吗?,clojure,Clojure,我需要遍历一个列表,对每个元素和不包括该元素的元素进行一些计算。例如,有一个列表(1231),我需要成对的(1)(231),(2)(131),(3)(1231)和(1)(231) (…)与每个元素以及不包括该元素的元素 每个元素听起来都像一张地图。排除该元素听起来像是一个过滤器。让我们从后者开始 user=> (filter #(not= % 1) '(1 2 3)) (2 3) 太好了。现在,让我们尝试将其映射到所有元素 user=> (let [coll '(1 2 3)] (

我需要遍历一个列表,对每个元素和不包括该元素的元素进行一些计算。例如,有一个列表
(1231)
,我需要成对的
(1)(231)
(2)(131)
(3)(1231)
(1)(231)

(…)与每个元素以及不包括该元素的元素

每个元素听起来都像一张地图。排除该元素听起来像是一个过滤器。让我们从后者开始

user=> (filter #(not= % 1) '(1 2 3))
(2 3)
太好了。现在,让我们尝试将其映射到所有元素

user=> (let [coll '(1 2 3)] (map (fn [elem] (filter #(not= % elem) coll)) coll))
((2 3) (1 3) (1 2))
创建实际的配对留给读者作为练习。提示:修改
map
中使用的闭包

请记住,上面建议的解决方案对于短列表应该可以很好地工作,但它的复杂性为O(n²)。另一个问题是没有正确处理具有重复项的集合

让我们采用递归方法。我们将基于
循环
递归

(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)]))))))
一个简单的例子:

user=> (pairs '(1 2 3))
[[(1) (2 3)] [(2) (1 3)] [(3) (1 2)]]
具有重复项的向量:

user=> (pairs [1 5 6 5])
[[(1) (5 6 5)] [(5) (1 6 5)] [(6) (1 5 5)] [(5) (1 5 6)]]

似乎是列表理解的工作:

(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)])
实际上,我将跳过为单个元素创建列表,这将使代码更加容易:

(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)])
如果需要保留副本,则可以使用索引集合:

(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)])

排除应该如何工作?仅排除此索引处的元素,或也排除与之相等的其他元素?列表是否可以有多个元素?如果是这样,下面的一些答案需要考虑到这一点。请参阅应仅排除给定索引处的元素。更新了问题。由于map和filter都是惰性的,所以只有当您了解所有列表时,它才会是O(n^2)。不管怎样,这都是O(n^2)。如果你有一个重复的列表呢?然后,
filter
将删除多个元素。我会用@skuro的答案来代替。@noahz,谢谢,说得好,我已经修改了答案。对投票人的一个善意的请求:你能花点时间重新阅读修改后的答案并分享你的想法吗?事实上,我的解决方案也是删除重复的答案。我对它进行了更新,以提供一个重复的安全版本。这类似于处理重复的方法——我唯一可以做的不同的事情是将循环/递归提取到一个helper fn中,并将递归调用封装在一个懒惰的seq中,以避免同时计算整个过程。+1关于#{x}的惯用用法作为第一个示例中的谓词。解决方案对列表进行排序,我希望保持原始顺序。
(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)])