newLISP Fan Club

Forum => newLISP in the real world => Topic started by: HPW on January 24, 2019, 11:06:17 PM

Title: csv to assoc-list
Post by: HPW on January 24, 2019, 11:06:17 PM
Hello,



Inspired by this thread:

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
Title: Re: csv to assoc-list
Post by: HPW on January 24, 2019, 11:13:13 PM
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
Title: Re: csv to assoc-list
Post by: HPW on January 24, 2019, 11:38:04 PM
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
Title: Re: csv to assoc-list
Post by: fdb on January 25, 2019, 01:11:41 PM
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))
Title: Re: csv to assoc-list
Post by: HPW on January 25, 2019, 09:29:36 PM
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
Title: Re: csv to assoc-list
Post by: rickyboy on January 25, 2019, 10:58:44 PM
HPW, just use fdb's code but remove the outer call to flat. That will get you what you want, i.e., "rows".
Title: Re: csv to assoc-list
Post by: HPW on January 26, 2019, 04:21:59 AM
Hello rickyboy,



Thanks for the hint. Works like a charm.



Regards
Title: Re: csv to assoc-list
Post by: HPW on January 27, 2019, 01:03:23 AM
Hello,



And finally when I need the assoc list into symbols:



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


Regards
Title: Re: csv to assoc-list
Post by: rickyboy on January 27, 2019, 04:32:57 PM
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
Title: Re: csv to assoc-list
Post by: HPW on January 28, 2019, 09:31:32 AM
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