Trying to "reduce" a sequence

Hi all,

I’ve been struggling with some code. I have a feeling there’s a lot of “background” I’ll need to get a hold of on this.

This code “works”. It’s useless, but it shows the general pattern I’m working on:

(let [them (map #(drop-nth % mylist) (range (count mylist)))]
  #_=>   (some first them))
123

I can even print each “them” and show they are as expected.

(let [them (map #(drop-nth % mylist) (range (count mylist)))]
  #_=> (prn them))
((123 654 23 56 45 234 45 435 3425 4565) (34 654 23 56 45 234 45 435 3425 4565)

I can happily reduce one of those “them”:

(reduce + '(123 654 23 56 45 234 45 435 3425 4565))
9605

But trying to put that into the above code causes issues:

(let [them (map #(drop-nth % mylist) (range (count mylist)))]
  #_=>  (reduce + them))

ClassCastException clojure.lang.LazySeq cannot be cast to java.lang.Number  clojure.lang.Numbers.add (Numbers.java:128)

Again, that code isn’t useful on its own, but I’ve stripped back the useful parts to get a minimal test case.

Various Google searches tell me that the issue here is map is lazy, but I get the same error when running it through doall.

Any assistance appreciated.

In this case, them is a list of lists. Your reduce + would only work on a list of numbers.

Depending on what you’re trying to accomplish, you’d need to do different things to get a list of numbers:

  • Use mapcat instead of map to flatten the list
  • Use first to get the first list
  • Use map to call reduce on each list

Hi,

Thanks for your reply. As I’ve done before, I tried to make a “minimal” example and produced something that is clearly broken for the reasons you describe. Here’s where I’m trying to go with this:

user=> (let [them (map #(drop-nth % mylist) (range (count mylist)))]
  #_=>   (some (= 1896 (reduce + them))))
ClassCastException clojure.lang.LazySeq cannot be cast to java.lang.Number  clojure.lang.Numbers.add (Numbers.java:128)

The point being “find me a version of mylist that adds up to a number after dropping one number”. Thought the “some” here would approach each list individually like it did in my first example of using “first”. I’ve lookeed at each of those potential solutions but I can’t make one fit?

Please don’t mark code as block quote. I edited you posts and now it has highlights. Learn more here https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown

Is it something like that?

(defn drop-nth [n coll]
  (keep-indexed #(if (not= %1 n) %2) coll))

(def mylist [3 112 3 55 3 66 123 4])
(def them (map #(drop-nth % mylist) (range (count mylist))))

(reduce #(if (= 366 (reduce + %2))
           (conj %1 %2)
           %1) [] them)

;; => [(112 3 55 3 66 123 4) (3 112 55 3 66 123 4) (3 112 3 55 66 123 4)]
1 Like

Thanks a heap, that looks like the right direction!

Just to wrap this up, here’s the “goal” code finished.

; Identifies the subcollection that adds to a goal number

(defn drop-nth [n coll]
  (keep-indexed #(if (not= %1 n) %2) coll))

(defn droppedlist [inlist]
  (map #(drop-nth % inlist) (range (count inlist))))

(defn scanadd
  [goal checklist]
  (if (empty? checklist)
  nil
  (some #(if (= goal (reduce + %1))
    %1
    (scanadd goal (droppedlist %1)))
  checklist)))

; Examples
addcollection.core=> (scanadd 68 (droppedlist '(60 345 435 23 435 234 8)))
(60 8)
addcollection.core=> (scanadd 67 (droppedlist '(60 345 435 23 435 234 8)))
nil

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.