获取当前元素和包含Clojure中其他所有内容的列表?

时间:2011-12-12 11:48:23

标签: clojure list-comprehension

获取包含当前元素对的列表以及包含所有其他元素的列表的最快方法是什么?这应该很快,因为列表可能包含一百万或更多元素。

例如,给定列表(1 2 3)

我想获取列表((1 (2 3)) (2 (1 3)) (3 (1 2)))

感谢您的帮助!

4 个答案:

答案 0 :(得分:6)

这将无需遍历遍历整个向量:

(defn this-and-that [xs]
  (map-indexed (fn [i x]
                [x (concat (take i xs) 
                           (drop (inc i) xs))])
              xs))

也适用于nils:

user=> (this-and-that [1 2 nil 3])
([1 (2 nil 3)] [2 (1 nil 3)] [nil (1 2 3)] [3 (1 2 nil)])

答案 1 :(得分:4)

“百万元素”并不是很多。试试这个是否足够快:

(defn this-and-that
  [s]
  (map-indexed (fn [i el]
                 [el (keep-indexed #(if (= %1 i)
                                            nil
                                            %2) s)]) s))

示例:

user> (this-and-that [1 2 3])
([1 (2 3)] [2 (1 3)] [3 (1 2)])

请注意,此代码对于包含nil的序列号无效。

答案 2 :(得分:4)

其他答案提供了很好的方法来做到这一点,但是你所描述的基本上是一个O(n ^ 2)操作,假设你实际上已经实现了所有的懒惰序列等。这可能不是一个好主意,如果n> = 1,000,000

您可能需要考虑扩大您正在考虑的代码范围,看看是否可以找到更有效的算法。

例如,您可能会发现将整个列表转换为向量,并根据索引访问向量编写算法更好。

答案 3 :(得分:1)

如何使用套装?

user> (let [xs #{1 2 3}]
        (for [x xs] [x (disj xs x)]))
([1 #{2 3}] [2 #{1 3}] [3 #{1 2}])

在一个拥有一百万件物品的套装上这样做时间并不算太糟糕:

(let [xs (set (range 1000000))]
  (time (count (for [x xs] [x (disj xs x)]))))
"Elapsed time: 841.668 msecs"
1000000