csv to assoc-list

Started by HPW, January 24, 2019, 11:06:17 PM

Previous topic - Next topic

HPW

Hello,



Inspired by this thread:

http://www.newlispfanclub.alh.net/forum/viewtopic.php?f=16&t=4918&p=24159&hilit=csv#p24159">http://www.newlispfanclub.alh.net/forum/viewtopic.php?f=16&t=4918&p=24159&hilit=csv#p24159



Using the artful-newlisp-master/csv.lsp I get a proper list.



The first sublist contains the column header names.



Now I want to transform the list to a assoc-list where the column header names get inserted in each other line as a assoc-key:



So ("Colname1" "Colname2" ....)

and

Lines (Val1 Val2 ....)

gets

(("Colname1" Val1)("Colname2" Val2) ...)



What is the shortest/best approach?



Regards



Hans-Peter
Hans-Peter

HPW

#1
Oops,



To early this morning. I think this will do the job.



> (map list '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))


Regards
Hans-Peter

HPW

#2
Hello,



My first approach:

(load "C:/Programme/newlisp/artful-newlisp-master/csv.lsp")
(setq csvlst(CSV:parse-file "C:/Programme/newlisp/csv_file.csv" ","))
(setq colnames (first csvlst))
(setq csvlst (rest csvlst))
(setq alst (list ))
(dolist (sublst csvlst)
    (setq alst(append alst (list(map list colnames sublst))))
)

Any better?



Rergards
Hans-Peter

fdb

#3
someting like:

(set 'csv '(("a" "b") (1 2) (3 4) (5 6)))

(flat (map (fn(x) (map list (first csv) x)) (rest csv)) 1)

=> (("a" 1) ("b" 2) ("a" 3) ("b" 4) ("a" 5) ("b" 6))

HPW

#4
Thanks for the code-sample.

But instead of your result:

(("a" 1) ("b" 2) ("a" 3) ("b" 4) ("a" 5) ("b" 6))

I want:

((("a" 1) ("b" 2)) (("a" 3) ("b" 4)) (("a" 5) ("b" 6)))

Regards
Hans-Peter

rickyboy

#5
HPW, just use fdb's code but remove the outer call to flat. That will get you what you want, i.e., "rows".
(λx. x x) (λx. x x)

HPW

#6
Hello rickyboy,



Thanks for the hint. Works like a charm.



Regards
Hans-Peter

HPW

#7
Hello,



And finally when I need the assoc list into symbols:



(map (fn (x) (set(sym(first x))(last x)))assoclst)


Regards
Hans-Peter

rickyboy

#8
Quote from: "HPW"And finally when I need the assoc list into symbols:



(map (fn (x) (set(sym(first x))(last x)))assoclst)

HPW,



With the above, you caused me to have a crazy thought.  Make a macro that does `let`-type bindings for you, given an assoc list; then, you could write any code under that `let` to do more computations.  Having a form of a `let` keeps the bindings local (i.e., does not pollute your top-level).



Here's the macro.  (Notice that I'm using your idea to make the bindings.)


(define-macro (let-alist [alist])
  (letex ([bindings]
          (map (fn (b) (list (sym (b 0)) (b 1)))
               (letex ([alist] [alist]) [alist]))
          [body]
          (cons 'begin (args)))
    (let [bindings] [body])))

Now, a simple usage: list `a` and `b` and their sum.


(let-alist '(("a" 3) ("b" 4))
  (list a b (+ a b)))
--> (3 4 7)

Here's a more complex usage: find the sum and average of the `a` and `b` columns.


(let (asum 0 bsum 0 N 0)
  (dolist (alist (csv->alists csv))
    (let-alist alist
      (inc asum a)
      (inc bsum b))
    (inc N))
  (list 'asum asum 'aavg (div asum N)
        'bsum bsum 'bavg (div bsum N)))
--> (asum 9 aavg 3 bsum 12 bavg 4)

Of course, `csv` is fdb's example:


(set 'csv '(("a" "b") (1 2) (3 4) (5 6)))
And the `csv->alists` function is just fdb's solution to your problem.


(define (csv->alists csv)
  (map (fn (x) (map list (first csv) x))
       (rest csv)))

There might be a simpler way.  Please let me know if you find one!  Cheers. --Rick
(λx. x x) (λx. x x)

HPW

#9
Hello rickyboy,



Yes, crazy but also cool. With this powerfull functions from newlisp I found the code harder to read and understand, but thats the power and beauty of newlisp. Thanks for sharing your ideas.



Regards
Hans-Peter