3

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

4

3 回答 3

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

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

(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)])
于 2012-11-28T19:50:34.067 回答
5

(...) 每个元素和不包括该元素的元素。

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

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²)。另一个问题是没有正确处理具有重复项的集合。

让我们采用递归方法。我们将基于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)]))))))

一个简单的例子:

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)]]
于 2012-11-28T14:04:36.323 回答
1
(def l [1 2 3])

(first (reduce (fn [[res ll] e]
                 [(conj res [(list e) (rest ll)])
                  (conj (vec (rest ll)) e)])
               [[] l] l))
=> [[(1) (2 3)] [(2) (3 1)] [(3) (1 2)]]
于 2012-11-28T17:24:44.223 回答