Author Topic: List Sorting  (Read 1996 times)

0 Members and 1 Guest are viewing this topic.

hendie

  • Guest
List Sorting
« on: March 22, 2007, 09:49:31 AM »
and now for my second post of the day (it's not been good so far !)

I have a list and each item in the list is composed of a number of elements, for example

BlockID Location Item Description SomethingElse

I need to sort this list by the Location THEN by the item
I've been using
Code: [Select]
(setq ListSorted2
       (vl-sort
Summarylist
'(lambda (s1 s2)
    (< (cadr s1) (cadr s2))
  )
       )
)
which will sort the list on one of the elements, but I then need it sorted on another sub-element without losing main order, if you get my drift.

example list
    Block3 GroundC XYZ BlahBlah xxxx
    Block1 GroundB RST BlahBlah xxxx
    Block5 GroundA ABC BlahBlah xxxx
    Block2 GroundA DEF BlahBlah xxxx

I need to return that list sorted as
    Block5 GroundA ABC BlahBlah xxxx
    Block2 GroundA DEF BlahBlah xxxx
    Block1 GroundB RST BlahBlah xxxx
    Block3 GroundC XYZ BlahBlah xxxx



John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9288
Re: List Sorting
« Reply #1 on: March 22, 2007, 10:10:45 AM »
Found this in my doc's folder. I think it could be of use

To expand on the example Vladimir gave briefly:

Given a list:
(setq lst '((2 . "A") (1 . "B") (4 . "D") (3 . "C") (5 . "E")))

To sort this list, using vla-sort, by the ALPHA we can use something like:
Code: [Select]
Command: (val-sort lst (lambda (x) (ascii (cdr x))))
((2 . "A") (1 . "B") (3 . "C") (4 . "D") (5 . "E"))

to sort this list by NUM we can use something like:
Code: [Select]
Command: (val-sort lst (lambda (x) (abs (car x))))
((1 . "B") (2 . "A") (3 . "C") (4 . "D") (5 . "E"))



Quote
From: Nesterovsky, Vladimir <vnestr@netvision.net.il>
Subject: Re: Sort a list numerically by first elements
Newsgroups: autodesk.autocad.customization
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Message-Id: <1113388@discussion.autodesk.com>
References: <1113385@discussion.autodesk.com>
Date: Thu, 25 Oct 2001 21:17:27 +0000

If you have a complex and potentially "heavy" key-retrieval
function (admittedly, not your simple case of CAR here),
then you better sort by value instead of by comparison:

(defun val-sort (lst valfun)
  (mapcar 'cdr
    (vl-sort
      (mapcar '(lambda(x) (cons (valfun x) x)) lst)
     '(lambda(a b)(< (car a) (car b))))))

For example, if you'd want to sort your list by hex-value of
the strings, you'd make a call

 (val-sort lst (lambda (x) (hex-val (cdr x))))


HTH
--
Have fun, :-)
Vlad   http://vnestr.tripod.com/
  (define (average . args)
    (if args (/ (apply '+ args) (length args))))



Jason Piercey <Jason@AtrEng.com> wrote in message
news:0E4759205497EDD0BD568DEBB6B9AE4F@in.WebX.maYIadrTaRb...
> I have a list of dotted pairs, the first element being an integer, the
> second being a string.
>
> ((2 . "A")  (1 . "B")  (3 . "C"))
>
> How would I go about sorting this list numerically by the first element o=
f
> each pair, so the return value is
>
> ((1 . "B") (2 . "A") (3 . "C"))
>
> I think I need to use mapcar and lambda, I'm just not versed well enough
> with those functions to figure it out.
>
> Thanks for you input.
>
> -Jason
>
>
>
>
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16727
  • Superior Stupidity at its best
Re: List Sorting
« Reply #2 on: March 22, 2007, 10:18:33 AM »
Not the simplest method, but an effective one, would be to place all of the items of the same "Location" into one list, then sort them according to "Item", then join the list together again ...

Code: [Select]
;set our counter to 1
(setq ndx 1)
(while (>(length mylist) 0) ;while we have a list to work with
 (set (read (strcat "*TEMP" (rtos ndx 2 0))) <all matching "location" items>) ;grab all of the matching locations - you need to edit this to make a list and extract as needed
 (foreach n (eval (read (strcat "*TEMP" (rtos ndx 2))))
    (setq mylist (vl-remove n mylist));remove the list items from mylist
 )
 <sort "*TEMPx" by item here>
 (setq ndx (1+ ndx))
)
<recombine lists in alphabetical order decrementing ndx back to 1>
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

uncoolperson

  • King Gator
  • Posts: 4430
  • Doing everything in metric inches!
Re: List Sorting
« Reply #3 on: March 22, 2007, 10:27:08 AM »
Code: [Select]
(SETQ thelist (LIST (LIST "Block3" "GroundC" "XYZ" "BlahBlah" "xxxx")
    (LIST "Block1" "GroundB" "RST" "BlahBlah" "xxxx")
    (LIST "Block5" "GroundA" "ABC" "BlahBlah" "xxxx")
    (LIST "Block2" "GroundA" "DEF" "BlahBlah" "xxxx")
      )
)

(SETQ summarylist
       (MAPCAR '(LAMBDA (apart)
  (LIST (CAR apart)
(VL-PRINC-TO-STRING (CDR apart))
  )
)
       thelist
       )
)

(SETQ listsorted2
       (VL-SORT summarylist
'(LAMBDA (s1 s2) (< (CADR s1) (CADR s2)))
       )
)
(SETQ summarylist2
       (MAPCAR '(LAMBDA (apart)
  (CONS (CAR apart) (READ (CADR apart)))
)
       listsorted2
       )
)


spits out

Quote
(("Block5" GROUNDA ABC BLAHBLAH XXXX) ("Block2" GROUNDA DEF BLAHBLAH XXXX) ("Block1" GROUNDB RST BLAHBLAH XXXX) ("Block3" GROUNDC XYZ BLAHBLAH XXXX))
when all else fails On Error Resume Next
-----------------------
Livin like I'm on borrowed time
-----------------------
Searching for the Ballmer Peak

VVA

  • Newt
  • Posts: 166
Re: List Sorting
« Reply #4 on: March 22, 2007, 10:31:30 AM »
Can be so
Code: [Select]
(setq Summarylist
       (list
         (list "Block3" "GroundC" "XYZ" "BlahBlah" "xxxx")
         (list "Block1" "GroundB" "RST" "BlahBlah" "xxxx")
         (list "Block5" "GroundA" "ABC" "BlahBlah" "xxxx")
         (list "Block2" "GroundA" "DEF" "BlahBlah" "xxxx")
         )
)

(mapcar (function (lambda (x) (nth x Summarylist)))
(vl-sort-i (mapcar '(lambda(x)(strcat (nth 1 x)(nth 2 x))) Summarylist)  '<))

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16727
  • Superior Stupidity at its best
Re: List Sorting
« Reply #5 on: March 22, 2007, 10:50:04 AM »
DOH!! .. why didn't I think of that ...
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

BrunoToniutti

  • Guest
Re: List Sorting
« Reply #6 on: March 22, 2007, 10:56:05 AM »
hi,
vl-sort does it directly or I misunderstood the problem

Code: [Select]
(vl-sort ls
  '(lambda (e1 e2)
     (and
       (< (cadr e1) (cadr e2))
       (< (caddr e1) (caddr e2))
     )
   )
)

Code: [Select]
(setq ls '(
           ("Block3" "GroundC" "XYZ" "BlahBlah" "xxxx")
           ("Block1" "GroundB" "RST" "BlahBlah" "xxxx")
           ("Block5" "GroundA" "ABC" "BlahBlah" "xxxx")
           ("Block2" "GroundA" "DEF" "BlahBlah" "xxxx")
          )
)
return :
(
("Block5" "GroundA" "ABC" "BlahBlah" "xxxx")
("Block2" "GroundA" "DEF" "BlahBlah" "xxxx")
("Block1" "GroundB" "RST" "BlahBlah" "xxxx")
("Block3" "GroundC" "XYZ" "BlahBlah" "xxxx")
)

edit 1 : don't use it, I think it's false, I need to test it more

edit 2 : its false, so I only find a way to use vl-sort directly if, as you write, element's length is fixed:
Code: [Select]
(vl-sort ls
  '(lambda (e1 e2)
     (< (strcat (cadr e1) (caddr e1)) (strcat (cadr e2) (caddr e2)))
   )
)

edit 3 : finally, I hope it's the good one :-)
Code: [Select]
(vl-sort ls
  '(lambda (e1 e2)
     (if (= (cadr e1) (cadr e2))
       (< (caddr e1) (caddr e2))
       (< (cadr e1) (cadr e2))
     )
   )
)

Bruno Toniutti
« Last Edit: March 22, 2007, 12:28:20 PM by BrunoToniutti »

hendie

  • Guest
Re: List Sorting
« Reply #7 on: March 22, 2007, 11:09:47 AM »
thanks a million guys, I can now move on to the next problem..... why is lisp so hard when you've been coding in VB for ages ????

CAB

  • Global Moderator
  • Seagull
  • Posts: 10376
Re: List Sorting
« Reply #8 on: March 26, 2007, 01:36:40 PM »
Been out of town, so here is a late entry.
Like Bruno's the items can be other than strings.

Code: [Select]
(defun compare-items (L1 L2)
  (cond
    ((equal (nth 1 L1) (nth 1 L2)) (< (nth 2 L1) (nth 2 L2)))
    (t (< (nth 1 L1) (nth 1 L2)))
  )
)


(mapcar '(lambda (x) (nth x lst)) (vl-sort-i lst 'compare-items))
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.