Reputation: 343
I have data like the following:
[["i2" "i1"]
['("red" "blue" "green" "yellow") '("C" "D" "A" "B")]]
I am trying to get it into the following format:
[["i1" "i2"]
['("A" "B" "C" "D") '("blue" "green" "red" "yellow")]]
Basically, I am trying to:
This is proving to be a difficult task for me. I tried constructing something like a three-level walk, but that did not work. I am trying to be idiomatic using the various map and walk functions, but maybe I just use "Do" and define a custom sorting map. It's pretty challenging.
Upvotes: 2
Views: 101
Reputation: 26446
(def data [["i2" "i1"] ['("red" "blue" "green" "yellow") '("C" "D" "A" "B")]])
(defn transpose [m] (apply mapv vector m))
(defn arrange [[x y]] (->> [x (map sort y)] transpose (sort-by first) transpose))
(arrange data)
;=> [["i1" "i2"] [("A" "B" "C" "D") ("blue" "green" "red" "yellow")]]
Upvotes: 2
Reputation: 8591
The replace fn is what you are looking for:
(defn my-sort [[cols vals]]
(let [ vals-sorted (map sort vals)
cols-sorted (sort cols)
cols->sorted-vals (zipmap cols vals-sorted)]
[cols-sorted
(replace cols->sorted-vals cols-sorted)]))
Upvotes: 1
Reputation: 2339
Here's how I would approach a problem like this to come up with a solution.
(defn rearrange [[cols vals]]
First, I'd note that I'm trying to sort ["i2" "i1"]
and rearrange the following list similarly. So I'll just tack the cols and value lists together:
(let [pairs (map list cols vals)]
Now pairs is a collection of data structures looking like: ("i2" ("red" "blue" "green" "yellow"))
. You want the function to return a vector.
(vector
Let's sort the pairs and grab the first item from each.
(mapv first (sort-by first pairs))
mapv
is just the same as (vec (map ...))
. sort-by
sorts pairs
by comparing (first item)
.
If we replace the first instance of first
in the line above with second
, then we get the corresponding lists of values in the correct order. But those lists won't themselves be sorted. So we add that:
(mapv (comp sort second) (sort-by first pairs)))))
End result:
(defn rearrange [[cols vals]]
(let [pairs (map list cols vals)]
(vector
(mapv first (sort-by first pairs))
(mapv (comp sort second) (sort-by first pairs)))))
It's not the nicest version of the function you can write, but half the battle is getting to this point. If you understand how this works, you can start improving it.
(def data [["i3" "i1" "i2"]
['("a" "c" "d" "b")
'("elephant" "zebra" "tiger" "cat")
'("red" "yellow" "blue" "green")]])
user=>(rearrange data)
[["i1" "i2" "i3"]
[("cat" "elephant" "tiger" "zebra")
("blue" "green" "red" "yellow")
("a" "b" "c" "d")]]
Upvotes: 3