clojure list manipulation multilist to list [duplicate] - clojure

This question already has answers here:
Clojure: Semi-Flattening a nested Sequence
(5 answers)
Closed 8 years ago.
Is there a clojure function to do:
((1 2) (3) (5 1) (2)) => (1 2 3 5 1 2)
(def a-list '((1 2) (3) (5 1) (2)))
(my-func a-list)
;; =>(1 2 3 5 1 2)

(apply concat a-list) ;; (1 2 3 5 1 2)

(flatten a-list)
will do the trick as well.
See:
http://clojuredocs.org/clojure_core/clojure.core/apply
http://clojuredocs.org/clojure_core/clojure.core/concat
http://clojuredocs.org/clojure_core/clojure.core/flatten

Related

How do I sum the inner sequence in a list of lists?

I want to take a sequence of sequences and sum up each inner sequence.
Data ((1 2 3) (2 3 4) (3 4 5) (4 5 6))
Desired output ((6) (9) (12) (15)) or (6 9 12 15)
I've tried apply map + which doesn't give the desired output. I've also experimented with reduce.
(map #(apply + %) '((1 2 3) (2 3 4) (3 4 5) (4 5 6)))
;; => (6 9 12 15)
(map #(list (apply + %)) '((1 2 3) (2 3 4) (3 4 5) (4 5 6)))
;; => ((6) (9) (12) (15))

Scheme: Mapping a list as argument to a function

If I have a function that takes 3 arguments, and returns a list:
(some-function 1 2 3) --> '(3 2 1)
and I have a list of lists like this:
( (1 2 3) (2 1 3) (3 2 1) )
How can I map "some-function" to use all the lists as elements?
Thank you.
If the lists are only nested once then it is possible to turn them into a single list using fold and append and call some-function on the result with apply i.e
(fold append '() '((1 2 3) (2 1 3) (3 2 1))) => (2 3 1 3 2 1 1 2 3)
(apply some-function (2 3 1 3 2 1 1 2 3))
Otherwise you can just wrap apply and the some-function in a lambda you pass to map
(map (lambda (x) (apply some-function x)) '((1 2 3) (2 1 3) (3 2 1)))
I am not sure what result you mean.
(define (rev-list a b c)
(list c b a))
(rev-list 1 2 3)
⇒ (3 2 1)
(apply rev-list '((1 2 3) (2 1 3) (3 2 1)))
⇒ ((3 2 1) (2 1 3) (1 2 3))
(map (lambda (l) (apply rev-list l)) '((1 2 3) (2 1 3) (3 2 1)))
⇒ ((3 2 1) (3 1 2) (1 2 3))

transpose a list of lists clojure [duplicate]

This question already has answers here:
Matrix transposition in clojure
(2 answers)
Closed 6 years ago.
I have a transpose function that works for fixed arities
(defn transpose [a b c]
(map list a b c))
(transpose '(1 2 3) '(4 5 6) '(7 8 9))
((1 4 7) (2 5 8) (3 6 9))
(apply transpose (list '(1 2 3) '(4 5 6) '(7 8 9)))
((1 4 7) (2 5 8) (3 6 9))
But how can I generalise this for n arguments so I could call it as follows:
(transpose '(1 2) '(4 5))
(transpose '(1 2 3) '(4 5 6) '(7 8 9))
...
I feel as thought I need something like the following
(defn transpose [& xs]
(apply (map list) xs))
But I can't get it to work.
You are so close:
(defn transpose [& xs]
(apply map list xs))

Clojure reverse-flattening lists. E.g. '(1 2 3 4 5 6) to '( (1 2) (3 4) (5 6)

Is there a core function or some idiomatic way to do a "reverse flattening" of a collection?
E.g. I would like the following:
(by-two '(1 2 3 4 5 6)) ; evals to '( (1 2) (3 4) (5 6) )
Of course the form in the above case would need an even number of elements or the function should do something sensible if presented with an odd-numbered collection. A generalized by-n function would be better of course. It's not clear to me whether there's any merit in trying to generalize the concept in depth as well or what's the best form to do so:
(by [2 2] '(1 2 3 4 5 6 7 8)) ; evals to '( ( (1 2) (3 4) ) ( (5 6) (7 8) ) )
(by [3 2 1 1 1] '(1 2 3 4 5 6)) ; evals to '(((((1 2 3) (4 5 6)))))
You can use reduce and partition :
(reduce #(partition %2 %1) '(1 2 3 4 5 6 7 8) [2 2])
There's partition:
(partition 2 [1 2 3 4 5])
> ((1 2) (3 4))
If you want to include the small tail, there's partition-all:
(partition-all 2 [1 2 3 4 5])
> ((1 2) (3 4) (5))
There is no such standard function I aware of. But partition is helpful:
(defn by [sizes coll]
(if sizes
(by (next sizes) (partition (first sizes) coll))
coll))

Is there an equivalent for the Zip function in Clojure Core or Contrib?

In Clojure, I want to combine two lists to give a list of pairs,
> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
In Haskell or Ruby the function is called zip. Implementing it is not difficult, but I wanted to make sure I wasn't missing a function in Core or Contrib.
There is a zip namespace in Core, but it is described as providing access to the Zipper functional technique, which does not appear to be what I am after.
Is there an equivalent function for combining 2 or more lists, in this way, in Core?
If there is not, is it because there is an idiomatic approach that renders the function unneeded?
(map vector '(1 2 3) '(4 5 6))
does what you want:
=> ([1 4] [2 5] [3 6])
Haskell needs a collection of zipWith (zipWith3, zipWith4, ...) functions, because they all need to be of a specific type; in particular, the number of input lists they accept needs to be fixed. (The zip, zip2, zip3, ... family can be regarded as a specialisation of the zipWith family for the common use case of tupling).
In contrast, Clojure and other Lisps have good support for variable arity functions; map is one of them and can be used for "tupling" in a manner similar to Haskell's
zipWith (\x y -> (x, y))
The idiomatic way to build a "tuple" in Clojure is to construct a short vector, as displayed above.
(Just for completeness, note that Haskell with some basic extensions does allow variable arity functions; using them requires a good understanding of the language, though, and the vanilla Haskell 98 probably doesn't support them at all, thus fixed arity functions are preferrable for the standard library.)
(partition 2 (interleave '(1 2 3) '(4 5 6)))
=> ((1 4) (2 5) (3 6))
or more generally
(defn zip [& colls]
(partition (count colls) (apply interleave colls)))
(zip '( 1 2 3) '(4 5 6)) ;=> ((1 4) (2 5) (3 6))
(zip '( 1 2 3) '(4 5 6) '(2 4 8)) ;=> ((1 4 2) (2 5 4) (3 6 8))
(map vector [1 2 3] [4 5 6])
to give you exactly what you wanted, mapping list across the two lists will give you a list of lists like in your example. I think that many Clojurians would tend to use vectors for this though it will work with anything. and the inputs do not need to be the same type. map creates seqs from them and then maps the seqs so any seq'able input will work fine.
(map list '(1 2 3) '(4 5 6))
(map list [1 2 3] '(4 5 6))
(map hash-map '(1 2 3) '(4 5 6))
(map hash-set '(1 2 3) '(4 5 6))
The built-in way would simply be the function 'interleave':
(interleave [1 2 3 4] [5 6 7 8]) => [1 5 2 6 3 7 4 8]
There is a function called zipmap, that may have the similar effect,
(zipmap (1 2 3)(4 5 6))
The ouput is as fllows:
{3 6, 2 5, 1 4}
#(apply map list %) transposes a matrix just like the Python zip* function. As a macro definition:
user=> (defmacro py-zip [lst] `(apply map list ~lst))
#'user/py-zip
user=> (py-zip '((1 2 3 4) (9 9 9 9) (5 6 7 8)))
((1 9 5) (2 9 6) (3 9 7) (4 9 8))
user=> (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))
((1 2 3 4) (9 9 9 9) (5 6 7 8))