在 Clojure 中迭代集合的所有对的惯用方法

发布于 2024-09-29 08:59:34 字数 330 浏览 8 评论 0原文

给定一个集合,我想迭代集合中的所有对。示例

(all-pairs seq)

(all-pairs '(a b c d)) => ([a b] [a c] [a d] [b c] [b d] [c d]))

这是我的想法

(defn all-pairs [coll]
  (for [ [idx elmt] (indexed coll)
         other-elmt (subvec coll (inc idx))]
     (vector elmt other-elm)))

,但感觉不惯用

Given a collection I want to iterate through all pairs in a collection. Example

(all-pairs seq)

(all-pairs '(a b c d)) => ([a b] [a c] [a d] [b c] [b d] [c d]))

Here is my idea

(defn all-pairs [coll]
  (for [ [idx elmt] (indexed coll)
         other-elmt (subvec coll (inc idx))]
     (vector elmt other-elm)))

But it doesn't feel idiomatic

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

瑾兮 2024-10-06 08:59:34

怎么样:

(use 'clojure.contrib.combinatorics)
(vec (map vec (combinations '(a b c d) 2)))

How about:

(use 'clojure.contrib.combinatorics)
(vec (map vec (combinations '(a b c d) 2)))
囍孤女 2024-10-06 08:59:34

比较懒,而且速度比较快。

(defn all-pairs [coll]
  (when-let [s (next coll)]
    (lazy-cat (for [y s] [(first coll) y])
              (all-pairs s))))

(defn all-pairs [coll]
  (let [x (first coll) xs (next coll)]
    (when xs
      (lazy-cat
       (map (fn [y] [x y]) xs) 
       (all-pairs xs)))))

(所有对 [1 2 3 4])
<代码>;; => ([1 2] [1 3] [1 4] [2 3] [2 4] [3 4])

(所有对 '(abcd))
<代码>;; => ([ab] [ac] [ad] [bc] [bd] [cd])

Lazy, and relatively fast.

(defn all-pairs [coll]
  (when-let [s (next coll)]
    (lazy-cat (for [y s] [(first coll) y])
              (all-pairs s))))

(defn all-pairs [coll]
  (let [x (first coll) xs (next coll)]
    (when xs
      (lazy-cat
       (map (fn [y] [x y]) xs) 
       (all-pairs xs)))))

(all-pairs [1 2 3 4])
;; => ([1 2] [1 3] [1 4] [2 3] [2 4] [3 4])

(all-pairs '(a b c d))
;; => ([a b] [a c] [a d] [b c] [b d] [c d])

人间☆小暴躁 2024-10-06 08:59:34
(defn all-pairs [coll]
  (loop [[x & xs] coll
         result []]
    (if (nil? xs)
      result
      (recur xs (concat result (map #(vector x %) xs))))))
(defn all-pairs [coll]
  (loop [[x & xs] coll
         result []]
    (if (nil? xs)
      result
      (recur xs (concat result (map #(vector x %) xs))))))
对你的占有欲 2024-10-06 08:59:34

我可以建议:

(defn all-pairs [sq] (for [i sq j sq] [i j]))

编辑:显然我误读了这个问题;由于您只需要不同的不重复对,因此如果您调用此函数的任何域上存在自然排序,我们仍然可以使用此方法。

(defn all-pairs [sq] (filter #(< (first %) (second %)) (for [i sq j sq] [i j])))

编辑2

另外:

(defn all-pairs [sq]
    (partition 2 (flatten (map (fn [sqi] (map #(vector %1 %2) sq sqi))
                   (take-while not-empty (iterate rest (rest sq)))))))

May I suggest:

(defn all-pairs [sq] (for [i sq j sq] [i j]))

EDIT: Clearly I misread the question; since you only want distinct unduplicated pairs, we can still use this approach if a natural ordering exists on whatever domain you're calling this function on.

(defn all-pairs [sq] (filter #(< (first %) (second %)) (for [i sq j sq] [i j])))

EDIT 2

Also:

(defn all-pairs [sq]
    (partition 2 (flatten (map (fn [sqi] (map #(vector %1 %2) sq sqi))
                   (take-while not-empty (iterate rest (rest sq)))))))
記柔刀 2024-10-06 08:59:34

如果您想以“学术风格”编写自己的组合函数,您可以尝试

(defn comb [xs m]
  (cond
    (= m 0) (list ())
    (empty? (seq xs)) ()
    :else (let [x (first xs)
                xs (rest xs)]
            (concat
             (map #(cons x %) (comb xs (- m 1)))
             (comb xs m)))))

然后将其应用到您的问题中,如下所示

(map vec (comb '(a b c d) 2))
<代码>([ab] [ac] [ad] [bc] [bd] [cd])

If you want to write your own combinations function in "academic style," you can try

(defn comb [xs m]
  (cond
    (= m 0) (list ())
    (empty? (seq xs)) ()
    :else (let [x (first xs)
                xs (rest xs)]
            (concat
             (map #(cons x %) (comb xs (- m 1)))
             (comb xs m)))))

and then apply it to your problem as follows

(map vec (comb '(a b c d) 2))
([a b] [a c] [a d] [b c] [b d] [c d])
如日中天 2024-10-06 08:59:34

一个简单的递归版本应该可以完成您想要的操作:

(defn all-pairs [coll]
  (let [x (first coll)
        xs (rest coll)]
    (if (empty? xs) 
      nil
      (concat 
        (map (fn [y] [x y]) xs) 
        (all-pairs xs)))))

A simple recursive version that should do what you want:

(defn all-pairs [coll]
  (let [x (first coll)
        xs (rest coll)]
    (if (empty? xs) 
      nil
      (concat 
        (map (fn [y] [x y]) xs) 
        (all-pairs xs)))))
三岁铭 2024-10-06 08:59:34

不是最快的解决方案,但是:

; handy helper function
(defn tails [v]
  "Given a sequence ( a b c ), returns all tails:  ( a b c ) ( b c ) ( c )"
  (when (seq v) 
    (lazy-cat (list v) (tails (rest v)))))

(defn pair* [v]
  "Match the first item in the list with all others in pairs."
  (when (> (count v) 1)
    (for [y v] [(first v) y])))

(defn all-pairs [v]
  (apply concat (map pair* (tails v))))

Not the fastest solution, but:

; handy helper function
(defn tails [v]
  "Given a sequence ( a b c ), returns all tails:  ( a b c ) ( b c ) ( c )"
  (when (seq v) 
    (lazy-cat (list v) (tails (rest v)))))

(defn pair* [v]
  "Match the first item in the list with all others in pairs."
  (when (> (count v) 1)
    (for [y v] [(first v) y])))

(defn all-pairs [v]
  (apply concat (map pair* (tails v))))
楠木可依 2024-10-06 08:59:34

这个怎么样?

(defn all-pairs [coll]
(when coll
  (concat (map vector (repeat (first coll)) (rest coll))
          (all-pairs (next coll)))))

或者,如果您寻求惰性序列:

(defn all-pairs [coll]
(lazy-seq
  (when coll
    (concat (map vector (repeat (first coll)) (rest coll))
            (all-pairs (next coll))))))

How about this?

(defn all-pairs [coll]
(when coll
  (concat (map vector (repeat (first coll)) (rest coll))
          (all-pairs (next coll)))))

Or, if you seek a lazy seq:

(defn all-pairs [coll]
(lazy-seq
  (when coll
    (concat (map vector (repeat (first coll)) (rest coll))
            (all-pairs (next coll))))))
水中月 2024-10-06 08:59:34

这又如何呢?

(defn seq->pairs 
  [s]
  (loop [res [] s s]
     (let [[head next] (split-at 2 s)
           res (conj res head)]
        (if (empty? next) res (recur res next)))))

What about this?

(defn seq->pairs 
  [s]
  (loop [res [] s s]
     (let [[head next] (split-at 2 s)
           res (conj res head)]
        (if (empty? next) res (recur res next)))))
眼睛会笑 2024-10-06 08:59:34

只是另一种可能的解决方案:

(defn all-pairs
        [c]
        (mapcat #(drop % %2)
                 (range 1 (count c))
                 (partition (count c) (for [a c b c] [a b]))))


(all-pairs '(a b c d)) => ([a b] [a c] [a d] [b c] [b d] [c d]))
(all-pairs [5 4 3 2 1]) => ([5 4] [5 3] [5 2] [5 1] [4 3] [4 2] [4 1] [3 2] [3 1] [2 1])
(all-pairs "pairs") => ([\p \a] [\p \i] [\p \r] [\p \s] [\a \i] [\a \r] [\a \s] [\i \r] [\i \s] [\r \s])

Just another possible solution:

(defn all-pairs
        [c]
        (mapcat #(drop % %2)
                 (range 1 (count c))
                 (partition (count c) (for [a c b c] [a b]))))


(all-pairs '(a b c d)) => ([a b] [a c] [a d] [b c] [b d] [c d]))
(all-pairs [5 4 3 2 1]) => ([5 4] [5 3] [5 2] [5 1] [4 3] [4 2] [4 1] [3 2] [3 1] [2 1])
(all-pairs "pairs") => ([\p \a] [\p \i] [\p \r] [\p \s] [\a \i] [\a \r] [\a \s] [\i \r] [\i \s] [\r \s])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文