csv to assoc-list

Q&A's, tips, howto's
Locked
HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

csv to assoc-list

Post by HPW »

Hello,

Inspired by this thread:
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
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

Oops,

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

Code: Select all

> (map list '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
Regards
Hans-Peter

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

Hello,

My first approach:

Code: Select all

(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
Posts: 66
Joined: Sat Nov 09, 2013 8:49 pm

Re: csv to assoc-list

Post by fdb »

someting like:

Code: Select all

(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
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

Thanks for the code-sample.
But instead of your result:

Code: Select all

(("a" 1) ("b" 2) ("a" 3) ("b" 4) ("a" 5) ("b" 6))
I want:

Code: Select all

((("a" 1) ("b" 2)) (("a" 3) ("b" 4)) (("a" 5) ("b" 6)))
Regards
Hans-Peter

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Re: csv to assoc-list

Post by rickyboy »

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
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

Hello rickyboy,

Thanks for the hint. Works like a charm.

Regards
Hans-Peter

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

Hello,

And finally when I need the assoc list into symbols:

Code: Select all

(map (fn (x) (set(sym(first x))(last x)))assoclst)
Regards
Hans-Peter

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Re: csv to assoc-list

Post by rickyboy »

HPW wrote:And finally when I need the assoc list into symbols:

Code: Select all

(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.)

Code: Select all

(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.

Code: Select all

(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.

Code: Select all

(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:

Code: Select all

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

Code: Select all

(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
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Re: csv to assoc-list

Post by HPW »

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

Locked