NOT - EXISTS / NOT - запрос типа IN в Clojure - PullRequest
1 голос
/ 03 сентября 2011

У меня есть 2 структуры данных, подобные приведенным ниже

(ns test)

(def l 
  [{:name "Sean" :age 27} 
   {:name "Ross" :age 27}
   {:name "Brian" :age 22}])

(def r 
  [{:owner "Sean" :item "Beer" }
   {:owner "Sean" :item "Pizza"}
   {:owner "Ross" :item "Computer"} 
   {:owner "Matt" :item "Bike"}])

Я хочу, чтобы у меня были люди, которым не принадлежит ни один предмет.(В данном случае Брайан, поэтому [{: name "Brian": возраст 22 года}] Если бы это был SQL, я бы сделал левое внешнее объединение или не существует, но я не уверен, как сделать это в clojure более производительным способом.

Ответы [ 2 ]

4 голосов
/ 03 сентября 2011

Хотя решение Чака, безусловно, является наиболее разумным, мне интересно, что можно написать решение в терминах реляционных алгебраических операторов, используя clojure.set:

(require '[clojure.set :as set])
(set/difference (set l)
                (set/project (set/join r l {:owner :name})
                             #{:name :age}))
; => #{{:name "Brian", :age 22}}
4 голосов
/ 03 сентября 2011

Вы в основном хотите сделать filter на l, но отрицательно. Мы могли бы просто not выполнить условие, но функция remove уже сделала это для нас. Так что-то вроде:

(let [owner-names (set (map :owner r))]
  (remove #(owner-names (% :name)) l))

(я думаю, что он читается лучше с набором, но если вы хотите избежать выделения набора, вы можете просто сделать (remove (fn [person] (some #(= (% :owner) (person :name)) r)) l).)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...