如何使用varargs进行过滤?

时间:2015-02-03 21:52:13

标签: clojure functional-programming

我有一张用户及其最喜欢的乐队地图:

(def data
  {
    :David {"Tribalistas" 3.0
       "Daft Punk" 5.0
       "Lorde" 4.0
       "Fall Out Boy" 1.0}

    :Matt {"Imagine Dragons" 3.0
      "Daft Punk" 4.0
      "Lorde" 4.0
      "Fall Out Boy" 1.0}

    :Ben {"Kacey Musgraves" 4.0
     "Imagine Dragons" 3.0
     "Lorde" 3.0
     "Fall Out Boy" 1.0}

}   )

我需要过滤具有两个共同键的结果,在本例中为band1和band2

(defn common-ratings [band1 band2 ratings]
  (filter #(and ((second %) band1) ((second %) band2)) ratings))


(common-ratings "Daft Punk" "Lorde" data) ; should return David and Matt lines

但是现在,我需要改变varargs中的乐队,我尝试使用类似的东西:

apply and...

所以我可以使用这样的函数:

(common-ratings "Daft Punk" "Lorde" "Another band" "Another Band2" data)

但它不起作用。

提前致谢

3 个答案:

答案 0 :(得分:2)

  • 如前所述,and是一个宏,所以不能成为一个参数 功能,apply或任何其他。
  • and最接近的标准函数是every?

由于您拥有未知数量的乐队,请将其作为集合传递:

(defn common-ratings [bands ratings]
  (filter #(every? (val %) bands) ratings))

...我已将second替换为val,以表明我们正在处理地图条目。

例如,

(common-ratings ["Daft Punk" "Lorde"] data)
;([:David {"Tribalistas" 3.0, "Daft Punk" 5.0, "Lorde" 4.0, "Fall Out Boy" 1.0}] [:Matt {"Imagine Dragons" 3.0, "Daft Punk" 4.0, "Lorde" 4.0, "Fall Out Boy" 1.0}])

如果你想将bands作为单个参数传递,最后将它们作为 rest 参数捕获它们:

(defn common-ratings [ratings & bands]
  ... )

...你这样称呼:

(common-ratings data "Daft Punk" "Lorde")

......具有与以前相同的效果。

答案 1 :(得分:0)

其中一个选项是将and宏包装到函数中:

(defn and-fn [x y] (and x y))

然后,您可以使用reduce代替apply来获得相同的结果:

(reduce and-fn [true true true false]) ; => false

为方便起见,最后一次减少可以包含在另一个函数中:

(defn and-multi [& args]
  (reduce #(and %1 %2) true args)) ; initial value is needed for invocation with no args

现在它的行为与普通的and宏非常相似:

(and-multi) ; => true
(and-multi false true) ; => false
(apply and-multi [true true true]) ; => true

它甚至与args的评估具有相同的行为:

(and false (range)) ; => false (despite of second param being infinite sequence)
(and-multi false (range)) ; => false

答案 2 :(得分:0)

非常感谢你们,我的最终解决方案非常接近@Thumbnail解决方案:

(defn common-ratings [& bands] (filter #(every? (second %) bands) data))