Jump to content

Recommended Posts

Posted (edited)

I need a lisp that I can use to load a txt file, sort it by the first element from smallest to largest, and then copy the resulting data into an existing txt file or into a new txt file.

I know this can be done using excel but I would prefer lisp.
Example txt file

15.65   792.42
10.07   793.79
10.02   794.10
9.98   794.08
6.70   794.34
6.62   794.73
7.27   794.57
10.11   794.47
11.54   794.48
11.53   795.01
5.12   794.70
5.18   795.04
13.51   794.92
13.51   794.18
3.40   795.44
2.55   795.61
3.19   795.60
2.99   795.76
2.29   795.77
2.04   795.95
2.79   795.93
2.63   796.09
1.84   796.09
1.55   796.28
2.54   796.25
2.33   795.16
2.32   795.56
2.24   796.22
0.00   796.26
1.08   795.78
1.03   796.26

 

Edited by SLW210
Code Tags!
Posted

1. That's not a text file, you just put some numbers into the forum editor.

 

2. You should have at least used Code Tags to post them. (<> in the editor toolbar), A .txt would have been better.

 

3. You should show an example, before, after, I have no idea what you want the end result to look like, you show 2 columns, are they sorted 1st number to last in 1 column or 2 columns, etc.?

Posted

Hi
I understand that it's sorting based on the first number in each row

Maybe this can help you

 

(defun c:draganK (/ nmarch nmarch1 arch arch1 linea separa<->campos lst lstA v)
  (defun separa<->campos (tx lstCtrs / c p l)
    (foreach c (vl-string->list tx)
      (if (member (setq c (chr c)) lstCtrs)
        (if p (setq l (cons (atof p) l) p nil))
        (setq p (if p (strcat p c) c))
      )
    )
    (reverse (if p (cons (atof p) l) l))
  )
  (setvar "DIMZIN" 0)
  (if (setq nmarch
	     (getfiled "Select source file"
		       ""
		       "*"
		       2
	     )
      )
    (if	(setq arch (open nmarch "r"))
      (if (setq	arch1
		 (open
		   (setq nmarch1 
		     (strcat
		       (vl-filename-directory nmarch)
		       "\\"
		       (vl-filename-base nmarch)
		       "_sorted"
		       (vl-filename-extension nmarch)
		     )
		   )
		   "w"
		 )
	  )
	(progn
	  (while (setq linea (read-line arch))
	    (setq lst  (separa<->campos linea '("," ";" " "))
		  lstA (cons lst lstA)
	    )
          )
	  (foreach v (vl-sort lstA '(lambda (a b) (< (car a) (car b))))
	    (write-line (foreach x v (setq s (if s (strcat s "\t" (rtos x 2 3)) (rtos x 2 3)))) arch1)
	    (setq s nil)
	  )
	)
      )
    )
  )
  (if arch
    (close arch)
  )
  (if arch1
    (progn
      (close arch1)
      (startapp "notepad" nmarch1)
    )
  )
  (princ)
)

 

  • Like 3
Posted (edited)

Sorting is done based on the first row, thanks for the help.

Edited by DraganK
Posted

So values in the second row remain with the sorted value in the first row?

Posted

@SLW210 Taking the text file as an example sorting a X & Y file. The lsta list is ((x y)(x y)...)

 

;x only
(setq lst (vl-sort lst '(lambda (x y) (< (car x)(car y)))))

 

Sorting on both X then Y

; sorts on 1st two items
(vl-sort lst
	 '(lambda (a b)
	    (cond
	      ((< (car a) (car b)))
	      ((= (car a) (car b)) 
		  (< (cadr a) (cadr b)))
	    )
	  )
)

 

It is possible to sort multiple levels I have a sort up to 5 levels I use it when looking at blocks with attributes, eg blkname color Xsize Ysize, then use that sorted list to count the common blocks.

 

A hint a lot of requests here need a sort on Y then X, so can reorder the sort. swapping car fpr cadr & cadr for car.

Some others

(acad_strlsort lst)

 

(defun BubbleSort (lstItems / blnFlag item1 item2 lstItems2)
 (setq item1 (car lstItems))
 (foreach item2 (cdr lstItems)
  (if (<= item1 item2)
   (setq lstItems2 (cons item1 lstItems2)
         item1     item2
   )
   (setq lstItems2 (cons item2 lstItems2)
         blnFlag   T
   )
  )
 )
 (if blnFlag
  (BubbleSort (reverse (cons item1 lstItems2)))
  (reverse (cons item1 lstItems2))
 )
)

 

Posted

Until I see a before and after I'm not wasting time on this.

Posted

If this is before... 

 

15.65   792.42
10.07   793.79
10.02   794.10
9.98   794.08
6.70   794.34
6.62   794.73
7.27   794.57
10.11   794.47
11.54   794.48
11.53   795.01
5.12   794.70
5.18   795.04
13.51   794.92
13.51   794.18
3.40   795.44
2.55   795.61
3.19   795.60
2.99   795.76
2.29   795.77
2.04   795.95
2.79   795.93
2.63   796.09
1.84   796.09
1.55   796.28
2.54   796.25
2.33   795.16
2.32   795.56
2.24   796.22
0.00   796.26
1.08   795.78
1.03   796.26

 

And this is after...

 

0.00   796.26
1.03   796.26
1.08   795.78
1.55   796.28
1.84   796.09
2.04   795.95
2.24   796.22
2.29   795.77
2.32   795.56
2.33   795.16
2.54   796.25
2.55   795.61
2.63   796.09
2.79   795.93
2.99   795.76
3.19   795.60
3.40   795.44
5.12   794.70
5.18   795.04
6.62   794.73
6.70   794.34
7.27   794.57
9.98   794.08
10.02   794.10
10.07   793.79
10.11   794.47
11.53   795.01
11.54   794.48
13.51   794.92
13.51   794.18
15.65   792.42

 

 

This should do the job.

 

(defun c:SortTxtCol ( / infile outfile data sortedData)

  ;; Split a string by space or tab
  (defun split-string (s / result start i c)
    (setq result '() start 0 i 0)
    (while (< i (strlen s))
      (setq c (substr s (+ i 1) 1))
      (if (member c '(" " "\t"))
        (progn
          (if (> i start)
            (setq result (cons (substr s (+ start 1) (- i start)) result))
          )
          (while (and (< i (strlen s)) (member (substr s (+ i 1) 1) '(" " "\t")))
            (setq i (1+ i))
          )
          (setq start i)
        )
        (setq i (1+ i))
      )
    )
    (if (> i start)
      (setq result (cons (substr s (+ start 1) (- i start)) result))
    )
    (reverse result)
  )

  ;; Read lines from a file and return list of (num1 num2)
  (defun read-lines (filename / fp lines line nums)
    (setq fp (open filename "r"))
    (setq lines '())
    (while (setq line (read-line fp))
      (setq nums (mapcar 'atof (split-string line)))
      (if (= (length nums) 2)
        (setq lines (cons nums lines))
      )
    )
    (close fp)
    (reverse lines)
  )

  ;; Write sorted data to output file
  (defun write-lines (filename lines / fp)
    (setq fp (open filename "w"))
    (foreach pair lines
      (write-line (strcat (rtos (car pair) 2 2) "   " (rtos (cadr pair) 2 2)) fp)
    )
    (close fp)
  )

  ;; Prompt for input and output
  (setq infile (getfiled "Select Input TXT File" "" "txt" 0))
  (setq outfile (getfiled "Select Output TXT File" "" "txt" 1))

  ;; Load, sort and write
  (setq data (read-lines infile))
  (setq sortedData (vl-sort data (function (lambda (a b) (< (car a) (car b))))))
  (write-lines outfile sortedData)

  (princ "\nSorting complete. Output written.\n")
  (princ)
)

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...