Reputation: 577
I need a function that takes two lists, e.g. (1 2 3 4) and (2 3 4 5), and returns their intersection, i.e. (2 3 4). I wrote up a function that works but it's 8 lines long and very "un-Clojurelike," owing to my newness to the sport. I know there's something elegant out there, hell, maybe even a Clojure keyword that solves the whole problem. The comparison needs to only be at the top level, not recursing through the entire list structures. Thank you in advance.
Upvotes: 3
Views: 859
Reputation: 577
As soon as I posted my question, I took another stab at it, and came up with this in a day:
(defmacro FindAtomInList [A L] `(first (drop-while #(not= ~A %) ~L))) ;; If Atom A is in List L, return it, otherwise, nil.
(defn Intersect [L1 L2] (filter some? (map #(FindAtomInList % L1) L2))) ;; Return the intersection of Lists 1 and 2. Empty if none.
Thank you for your help. The repl is an amazing development tool. I like the idea of a library for set operation. I should have guessed there was such a thing.
Upvotes: 0
Reputation: 29958
Besides the standard answer above, if for some reason you need to retain the original order you could use a technique like this:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(let [a [1 2 3 4]
b [3 4 5]
result (filterv (set a) b) ]
(is= result [3 4]))
based on my favorite template project. Please see also the list of documentation, especially the Clojure CheatSheet.
Upvotes: 2
Reputation: 1852
There is built-in library for set operation if you don't mind the sequence of result set.
(require '[clojure.set :as set])
(set/intersection (set '(1 2 3 4) ) (set '( 3 4 5))) ; ==> returns #{4 3}
Upvotes: 6