Comments on: Lisp: Parse and Aggregate a CSV File http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/ I will not fix your computer. Tue, 04 Aug 2020 22:34:33 +0000 hourly 1 https://wordpress.org/?v=4.7.26 By: Frank Shearar http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-13540 Tue, 10 Nov 2009 12:27:15 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-13540

It’s very common for CSV files to allow the comma as part of a field… as long as the field’s quoted. For instance:

1,2,”3,4″,5.

SPLIT-SEQUENCE will, I imagine, misparse the 3rd field and say that the line contains 5 fields when it only contains 4.

Further, quoted fields can themselves contain quotes, escaped as “”. So this is a legal CSV line too:

1,2″Then I was all like “”so what?”””

And the final thing is that quoted fields may contain linebreaks. (I must say, I’ve never seen this in the field!)

Reply  |  Quote
]]>
By: Lisp: Parse and Aggregate a CSV File [ Terminally Incoherent ] http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-9280 Sun, 08 Jun 2008 09:22:34 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-9280

[…] December 22nd 2007 4:58pm [-] From: terminally-incoherent.com Related? […]

]]>
By: Jaba http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7463 Mon, 24 Dec 2007 09:52:57 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7463

:D intresting, I’ll try vim so, thanks!

Reply  |  Quote
]]>
By: Luke Maciak http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7462 Mon, 24 Dec 2007 08:56:33 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7462

Ah! Let* – that’s what I was looking for. Funny thing – I completely forgot that it exists. Thanks!

Re: editor – Vim all the way! I run it as my default text editor in every single OS. ;)

Reply  |  Quote
]]>
By: Jaba http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7461 Mon, 24 Dec 2007 08:46:08 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7461

I still haven’t tried your code (I’m packing for holydays, I’ve a fly for this evening!), but as requested I tried to make it “a little lispier” without changing what you did. It’s just a taste matter, in this case, but the result is really good. Some problems, you simply have to resolve in simil-imperative way. But one thing I really love of lisp is that you CAN do anything, even imperative, you just don’t HAVE to. Ever heard of CLOS, the Common Lisp Object System? :D
http://cl-cookbook.sourceforge.net/clos-tutorial/index.html
Yes, in lisp you CAN go object oriented (and LOOK AT THE TUTORIAL, it’s soooo simple…), but you don’t have to. Usually, you just need some struct, that comes with free get/set functions :D
Just try it, if you wish, and let me know ;) have fun!

-J


  ;;; CVS PARSING FUNCTION - EXECUTABLE FILE  ; tree ";" for big comments, two for full-line comments, one for in-line comments... just conventions, as *global-variable*...
(load "split-sequence.lisp")
(setf aggregate nil) ; setf is setq when needed, but it's more flexible in general
 (parse-csv)	; this way you call a normal function, that can be reused
 
 ;; I formatted it a little more lispy, as teached in "Common Lisp - A gentle introduction to symbolic computation"
 ;; It's esasier with spaces than with tabs. Suggested base tabulation is of 2 spaces
(defun parse-csv (&optional (filename (first *args*)))	; &optional says: if you give parse-csv an argument, it's the filename; otherwise, get it from (first *args)
  "Parses a CSV file and DOES THINGS"  ; in-line documentation. Try (documentation 'parse-csv 'function) :D
  (with-open-file (stream filename) 
    (do ((line (read-line stream nil) (read-line stream nil))) 
        ((null line) aggregate) ; returns the aggregate value in output - no need to print it
	    (let* (		; let* is equivalent to let but bounds its arguments one at a time
		    (tmp    (split-sequence:SPLIT-SEQUENCE #\, line )) 	; this can still be made in LET*
		    (key    (intern (first tmp)))
		    (newval (parse-integer (car (last tmp)) :junk-allowed t)) ; CAR is lispy :P
		    (val    (cdr (assoc key aggregate))) ) ; this can stay in LET* too
          (if val   (rplacd (assoc key aggregate) (+ newval val))
	   		        (setq aggregate (acons key newval aggregate))))))


ps I code under linux with clisp (sometimes cmucl), simply using kwrite as editor (no time to learn emacs still… and gedit doesn’t have lisp highlighting). Under windows, the best editor i ever used is NOTEPAD++ (google it, you won’t regret it)

Reply  |  Quote
]]>
By: Luke Maciak http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7460 Mon, 24 Dec 2007 04:14:38 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7460

Here is a cleaner version with let… Still trying to figure out how to make it more lispy:

;;; get split-sequence from http://www.cliki.net/SPLIT-SEQUENCE
(load "split-sequence.lisp")
(setq aggregate '()) ;; the association list to store results

(with-open-file (stream (first *args*)) ;; open the file specified on cli
    (do ((line (read-line stream nil) 	;;; initialize with read-line
               (read-line stream nil))) ;;; step is read-line
        ((null line)) 			;;; termination condition
	
	;; split the output string on a comma using the split-sequence
	(setq tmp (split-sequence:SPLIT-SEQUENCE #\, line ) )

	(let (
		(key 	(intern (first tmp))					) 	;; our key
		(newval (parse-integer (first (last tmp)) :junk-allowed t)	)	;; convert the last value to an int
	     )
		   (setq val 	(cdr (assoc key aggregate))	)	;; check if key is in the assoc; if it's not, VAL will be NIL
		    
		   (if val
	  		(rplacd (assoc key aggregate) (+ newval val)) 	;; if exist update old entry
	   		(setq aggregate (acons key newval aggregate))	;; else add a new entry
		)
	)
    )
    (print aggregate)
)
Reply  |  Quote
]]>
By: Luke Maciak http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7459 Mon, 24 Dec 2007 03:56:25 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7459

I fixed your entries. You missed a </pre> tag here and there. And yeah, the preview button is there for times like this. But no worries.

Thanks for the code samples! I wish the comments were in English :P

Reply  |  Quote
]]>
By: Jaba http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7458 Sun, 23 Dec 2007 22:48:06 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7458

(sorry, never posted before on wordpress, I’m seeing only now the “preview” button… this will never occour again, please edit my previous entry, thank you)

You’re too polite not to try it immediatly. I’m pasting a lisp implementation of a simple local search algorithm, that tries to find a number with as many “ones” as possible in his binary representation, with solution space 0 to n. Sorry for the documentation in Italian :P

PSEUDO-CODE:

init(start);
i:=istart;
repeat
  generate (j in Nh(i))
  if fit(j) >= fit(i) then i:=j;
until f(j)

(defun dec2bin (n)  ; ci serve per ottenere la rappresentazione binaria del max
  "Restituisce la rappresentazione binaria di N, come lista di bit"
  (dec2bin-acc n nil))

(defun dec2bin-acc (n acc)
  "Versione di dec2bin con accumulatore per tail recursion"
  (if (= (length lst) n) lst
    (expand-bin (cons 0 lst) n)))

(defun fitness (n)
  "Restituisce la fitness di un numero"
  (length (remove-if #'zerop n)) )

(defun generate (i top) ;; a partire da questa versione, top è un numero decimale
  "Restituisce il primo tra i migliori vicini di I, stando attento a non sforare TOP"
  (let ((pos (position 0 i :from-end t)))
    (if (null pos) i
      (let ((copy (copy-list i)))
        (setf (nth pos copy) 1)
        (if (= (fitness i) (fitness j)) )

(defun best (lst)
  "Data una lista di codifiche binarie, restituisce quella con fitness migliore"
  (car (sort lst #'best-fit-check)) )

(defun local-search (n)
  "Esegue una ricerca locale con spazio delle soluzioni tra 0 e N"
  (do* ((i     (init n)     (best (list i j)))
        (j     (generate i n) (generate i n))
        (i-dec (bin2dec i)  (bin2dec i))
        (fi    (fitness i)  (fitness i))         ;NOTA: solo per leggibilità, per ottimizzazione rimuoverle
        (fj    (fitness j)  (fitness j)))
       ((or (equal i j) (> fi fj))  ; ecco che vado ad assicurarmi dal loop sul massimo
        (format t #|"~&FINE:|#"~&Soluzione finale:  ~D = ~A - Fitness: ~D" i-dec i fi)
         i-dec)
       (format t "~&Passaggio attuale: ~D = ~A - Fitness: ~D" i-dec i fi) ))

with much care on training on the “tail recursion” technic, that can generate code as fast as fortran does (look at “performance” on CLISP homepage)

Hope this can help, I spent some months to gain functional mentality – and it’s still work in progress.

Have fun with lisp

-J

Reply  |  Quote
]]>
By: Jaba http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7457 Sun, 23 Dec 2007 22:42:23 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7457

You’re too polite not to try it immediatly. I’m pasting a lisp implementation of a simple local search algorithm, that tries to find a number with as many “ones” as possible in his binary representation, with solution space 0 to n. Sorry for the documentation in Italian :P

PSEUDO-CODE:

init(start);
i:=istart;
repeat
  generate (j in Nh(i))
  if fit(j) >= fit(i) then i:=j;
until f(j) 
(defun dec2bin (n)  ; ci serve per ottenere la rappresentazione binaria del max
  "Restituisce la rappresentazione binaria di N, come lista di bit"
  (dec2bin-acc n nil))

(defun dec2bin-acc (n acc)
  "Versione di dec2bin con accumulatore per tail recursion"
  (if (= (length lst) n) lst
    (expand-bin (cons 0 lst) n)))

(defun fitness (n)
  "Restituisce la fitness di un numero"
  (length (remove-if #'zerop n)) )

(defun generate (i top) ;; a partire da questa versione, top è un numero decimale
  "Restituisce il primo tra i migliori vicini di I, stando attento a non sforare TOP"
  (let ((pos (position 0 i :from-end t)))
    (if (null pos) i
      (let ((copy (copy-list i)))
        (setf (nth pos copy) 1)
        (if (= (fitness i) (fitness j)) )

(defun best (lst)
  "Data una lista di codifiche binarie, restituisce quella con fitness migliore"
  (car (sort lst #'best-fit-check)) )

(defun local-search (n)
  "Esegue una ricerca locale con spazio delle soluzioni tra 0 e N"
  (do* ((i     (init n)     (best (list i j)))
        (j     (generate i n) (generate i n))
        (i-dec (bin2dec i)  (bin2dec i))
        (fi    (fitness i)  (fitness i))         ;NOTA: solo per leggibilità, per ottimizzazione rimuoverle
        (fj    (fitness j)  (fitness j)))
       ((or (equal i j) (> fi fj))  ; ecco che vado ad assicurarmi dal loop sul massimo
        (format t #|"~&FINE:|#"~&Soluzione finale:  ~D = ~A - Fitness: ~D" i-dec i fi)
         i-dec)
       (format t "~&Passaggio attuale: ~D = ~A - Fitness: ~D" i-dec i fi) ))

Hope this can help, I spent some months to gain functional mentality – and it’s still work in progress.

Have fun with lisp

-J

Reply  |  Quote
]]>
By: Jaba http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7456 Sun, 23 Dec 2007 22:40:58 +0000 http://www.terminally-incoherent.com/blog/2007/12/22/lisp-parse-and-aggregate-a-csv-file/#comment-7456

You’re too polite not to try it immediatly. I’m pasting a lisp implementation of a simple local search algorithm, that tries to find a number with as many “ones” as possible in his binary representation, with solution space 0 to n. Sorry for the documentation in Italian :P

PSEUDO-CODE:

init(start);
i:=istart;
repeat
  generate (j in Nh(i))
  if fit(j) >= fit(i) then i:=j;
until f(j)

WORKING LISP IMPLEMENTATION:
with much care on training on the “tail recursion” technic, that can generate code as fast as fortran does (look at “performance” on CLISP homepage)

(defun dec2bin (n)  ; ci serve per ottenere la rappresentazione binaria del max
  "Restituisce la rappresentazione binaria di N, come lista di bit"
  (dec2bin-acc n nil))

(defun dec2bin-acc (n acc)
  "Versione di dec2bin con accumulatore per tail recursion"
  (if (= (length lst) n) lst
    (expand-bin (cons 0 lst) n)))

(defun fitness (n)
  "Restituisce la fitness di un numero"
  (length (remove-if #'zerop n)) )

(defun generate (i top) ;; a partire da questa versione, top è un numero decimale
  "Restituisce il primo tra i migliori vicini di I, stando attento a non sforare TOP"
  (let ((pos (position 0 i :from-end t)))
    (if (null pos) i
      (let ((copy (copy-list i)))
        (setf (nth pos copy) 1)
        (if (= (fitness i) (fitness j)) )

(defun best (lst)
  "Data una lista di codifiche binarie, restituisce quella con fitness migliore"
  (car (sort lst #'best-fit-check)) )

(defun local-search (n)
  "Esegue una ricerca locale con spazio delle soluzioni tra 0 e N"
  (do* ((i     (init n)     (best (list i j)))
        (j     (generate i n) (generate i n))
        (i-dec (bin2dec i)  (bin2dec i))
        (fi    (fitness i)  (fitness i))         ;NOTA: solo per leggibilità, per ottimizzazione rimuoverle
        (fj    (fitness j)  (fitness j)))
       ((or (equal i j) (> fi fj))  ; ecco che vado ad assicurarmi dal loop sul massimo
        (format t #|"~&FINE:|#"~&Soluzione finale:  ~D = ~A - Fitness: ~D" i-dec i fi)
         i-dec)
       (format t "~&Passaggio attuale: ~D = ~A - Fitness: ~D" i-dec i fi) ))

Hope this can help, I spent some months to gain functional mentality – and it’s still work in progress.

Have fun with lisp

-J

Reply  |  Quote
]]>