Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Methods to sort a list of lists.

33 REPLIES 33
Reply
Message 1 of 34
Anonymous
1516 Views, 33 Replies

Methods to sort a list of lists.

If I want to sort a list of lists... say on the 3rd element of each how
might I go about this?

The following logic is what I thought of ?

process the lists moving all the 3rd elements to the head of each list.
extract all the car elements (was the 3rd el) into their own list.
sort this with acad_strlsort if each is a string or with a number
sorting routine if they are integers or reals.
reprocess the original list with a foreach on the sorted car elements
moving them from the origninal lists to a new list.
process the new sorted list moving all the car elements back to the 3rd
position.

problem...
If I have two or more lists that are similar like

(4 "MIKE" "MARY" "BECKY" "ALICE")
(4 "MIKE" "BILL" "BECKY" "ALICE")
(4 "MIKE" "ANNA" "BECKY" "ALICE")

How can I get them to sort like this:
(3 "MIKE" "ANNA" "BECKY" "ALICE")
(3 "MIKE" "BILL" "BECKY" "ALICE")
(3 "MIKE" "MARY" "BECKY" "ALICE")

In this case all three lists have an identical 3rd element, but in each
list the 2nd elements are different.
I suppose I would want them to sort first on the 3rd element then on the
1rst element.
but how would my application know just how the lists vary or are similar
but not exactly the same.

Any thougts?
33 REPLIES 33
Message 2 of 34
Anonymous
in reply to: Anonymous

Mike Hutchinson,

Here is my first try:

(setq lst1 '(4 "MIKE" "MARY" "BECKY" "ALICE"))
(setq lst2 '(4 "MIKE" "BILL" "BECKY" "ALICE"))
(setq lst3 '(4 "MIKE" "ANNA" "BECKY" "ALICE"))

(setq lst (list lst1 lst2 lst3))

(defun sort-by-third-ele (lst / lst_lst)
(mapcar '(lambda (x) (cadr (assoc x lst_lst)))
(vl-sort
(mapcar
'car
(setq lst_lst
(mapcar
'(lambda (item) (list (caddr item) item))
lst)))
'<)))

(sort-by-third-ele lst)

((4 "MIKE" "ANNA" "BECKY" "ALICE")
(4 "MIKE" "BILL" "BECKY" "ALICE")
(4 "MIKE" "MARY" "BECKY" "ALICE"))
Message 3 of 34
Anonymous
in reply to: Anonymous

Luis has the right idea using vl-sort. Here's another approach:

Command: (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("C" "b" 1 3 2)))
(("D" "a" 3 2 1) ("B" "c" 2 1 3) ("C" "b" 1 3 2))

Since items in a list are counted from 0, the third element of lst would be (nth
2 lst)...
Command: (vl-sort lst (function (lambda (a b)(< (nth 2 a)(nth 2 b)))))
(("C" "b" 1 3 2) ("B" "c" 2 1 3) ("D" "a" 3 2 1))

To sort on the second element...
Command: (vl-sort lst (function (lambda (a b)(< (nth 1 a)(nth 1 b)))))
(("D" "a" 3 2 1) ("C" "b" 1 3 2) ("B" "c" 2 1 3))

--
John Uhden, Cadlantic/formerly CADvantage
http://www.cadlantic.com
Sea Girt, NJ


"Mike Hutchinson" wrote in message
news:3D5030DE.B5166205@bbsae.com...
> If I want to sort a list of lists... say on the 3rd element of each how
> might I go about this?
>
> The following logic is what I thought of ?
>
> process the lists moving all the 3rd elements to the head of each list.
> extract all the car elements (was the 3rd el) into their own list.
> sort this with acad_strlsort if each is a string or with a number
> sorting routine if they are integers or reals.
> reprocess the original list with a foreach on the sorted car elements
> moving them from the origninal lists to a new list.
> process the new sorted list moving all the car elements back to the 3rd
> position.
>
> problem...
> If I have two or more lists that are similar like
>
> (4 "MIKE" "MARY" "BECKY" "ALICE")
> (4 "MIKE" "BILL" "BECKY" "ALICE")
> (4 "MIKE" "ANNA" "BECKY" "ALICE")
>
> How can I get them to sort like this:
> (3 "MIKE" "ANNA" "BECKY" "ALICE")
> (3 "MIKE" "BILL" "BECKY" "ALICE")
> (3 "MIKE" "MARY" "BECKY" "ALICE")
>
> In this case all three lists have an identical 3rd element, but in each
> list the 2nd elements are different.
> I suppose I would want them to sort first on the 3rd element then on the
> 1rst element.
> but how would my application know just how the lists vary or are similar
> but not exactly the same.
>
> Any thougts?
>
>
>
>
>
Message 4 of 34
Anonymous
in reply to: Anonymous

OK... let me compile a more complex list and attach it... I'll be back!

Mike Hutchinson wrote:

> If I want to sort a list of lists... say on the 3rd element of each how
> might I go about this?
>
> The following logic is what I thought of ?
>
> process the lists moving all the 3rd elements to the head of each list.
> extract all the car elements (was the 3rd el) into their own list.
> sort this with acad_strlsort if each is a string or with a number
> sorting routine if they are integers or reals.
> reprocess the original list with a foreach on the sorted car elements
> moving them from the origninal lists to a new list.
> process the new sorted list moving all the car elements back to the 3rd
> position.
>
> problem...
> If I have two or more lists that are similar like
>
> (4 "MIKE" "MARY" "BECKY" "ALICE")
> (4 "MIKE" "BILL" "BECKY" "ALICE")
> (4 "MIKE" "ANNA" "BECKY" "ALICE")
>
> How can I get them to sort like this:
> (3 "MIKE" "ANNA" "BECKY" "ALICE")
> (3 "MIKE" "BILL" "BECKY" "ALICE")
> (3 "MIKE" "MARY" "BECKY" "ALICE")
>
> In this case all three lists have an identical 3rd element, but in each
> list the 2nd elements are different.
> I suppose I would want them to sort first on the 3rd element then on the
> 1rst element.
> but how would my application know just how the lists vary or are similar
> but not exactly the same.
>
> Any thougts?
Message 5 of 34
Anonymous
in reply to: Anonymous

Very good sample John, I was way over...
Message 6 of 34
Anonymous
in reply to: Anonymous

OK... what I am looking for is that you could pass in lists of vertually any
size (all the same number of elements of course)
but mixed types... string integers or reals
right now the application I have in mind uses 10 elements.
Then specify in a second parameter list specifiing just how you want it sorted

a little complex but you get the idea ?
(setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2 1)("E"
"a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
(setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)

(Sorttheselists LstOfLists SortOrderSpec)

what I would want this to do is sort the list
first by the 2nd element in a ascending order,
then by the 4th element in a ascending order,
lastly by the 3rd element in a ascending order.

in any one call the number of sort specs could not exceed the number of
elements in each list.
all the lists would have to be the same number of elements.
all lists would have to be in the same order with regards to data type... (str
int int real str str)

with the above sort specs the result should be like this...
(("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c" 2 1
3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))

this is quit similar to how excel sort is... (I know I could harness excel to
do it for me perhaps but I don't have the knowledge to get lisp (or VBA) to do
it... )

The only other problem this might have in my application is the number of
lists could be quit large perhaps as many as 100 or more, but probably not as
many as 500. In my experience older programs using older bubble sort
functions could error out exceeding the stack (forget what the stack was
called just now)

anyway... that's it.

Mike Hutchinson wrote:

> OK... let me compile a more complex list and attach it... I'll be back!
>
> Mike Hutchinson wrote:
>
> > If I want to sort a list of lists... say on the 3rd element of each how
> > might I go about this?
> >
> > The following logic is what I thought of ?
> >
> > process the lists moving all the 3rd elements to the head of each list.
> > extract all the car elements (was the 3rd el) into their own list.
> > sort this with acad_strlsort if each is a string or with a number
> > sorting routine if they are integers or reals.
> > reprocess the original list with a foreach on the sorted car elements
> > moving them from the origninal lists to a new list.
> > process the new sorted list moving all the car elements back to the 3rd
> > position.
> >
> > problem...
> > If I have two or more lists that are similar like
> >
> > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> >
> > How can I get them to sort like this:
> > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > (3 "MIKE" "MARY" "BECKY" "ALICE")
> >
> > In this case all three lists have an identical 3rd element, but in each
> > list the 2nd elements are different.
> > I suppose I would want them to sort first on the 3rd element then on the
> > 1rst element.
> > but how would my application know just how the lists vary or are similar
> > but not exactly the same.
> >
> > Any thougts?
Message 7 of 34
Anonymous
in reply to: Anonymous

Another question... what does the function by the name "function" do ?
the help says that it ... tells the Visual LISP compiler to link and optimize the
argument as if it were a built-in function or defun.
does this use less memory or cause it to run faster or what ?
I suppose that it is recommended to use it ?


John Uhden wrote:

> Luis has the right idea using vl-sort. Here's another approach:
>
> Command: (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("C" "b" 1 3 2)))
> (("D" "a" 3 2 1) ("B" "c" 2 1 3) ("C" "b" 1 3 2))
>
> Since items in a list are counted from 0, the third element of lst would be (nth
> 2 lst)...
> Command: (vl-sort lst (function (lambda (a b)(< (nth 2 a)(nth 2 b)))))
> (("C" "b" 1 3 2) ("B" "c" 2 1 3) ("D" "a" 3 2 1))
>
> To sort on the second element...
> Command: (vl-sort lst (function (lambda (a b)(< (nth 1 a)(nth 1 b)))))
> (("D" "a" 3 2 1) ("C" "b" 1 3 2) ("B" "c" 2 1 3))
>
> --
> John Uhden, Cadlantic/formerly CADvantage
> http://www.cadlantic.com
> Sea Girt, NJ
>
> "Mike Hutchinson" wrote in message
> news:3D5030DE.B5166205@bbsae.com...
> > If I want to sort a list of lists... say on the 3rd element of each how
> > might I go about this?
> >
> > The following logic is what I thought of ?
> >
> > process the lists moving all the 3rd elements to the head of each list.
> > extract all the car elements (was the 3rd el) into their own list.
> > sort this with acad_strlsort if each is a string or with a number
> > sorting routine if they are integers or reals.
> > reprocess the original list with a foreach on the sorted car elements
> > moving them from the origninal lists to a new list.
> > process the new sorted list moving all the car elements back to the 3rd
> > position.
> >
> > problem...
> > If I have two or more lists that are similar like
> >
> > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> >
> > How can I get them to sort like this:
> > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > (3 "MIKE" "MARY" "BECKY" "ALICE")
> >
> > In this case all three lists have an identical 3rd element, but in each
> > list the 2nd elements are different.
> > I suppose I would want them to sort first on the 3rd element then on the
> > 1rst element.
> > but how would my application know just how the lists vary or are similar
> > but not exactly the same.
> >
> > Any thougts?
> >
> >
> >
> >
> >
Message 8 of 34
Anonymous
in reply to: Anonymous

And what would that be worth to ya? 🙂
Since you appear to understand how to write the program yourself, perhaps
a hint will do.

Your sortspec is in order of descending importance so do the last
sort first and so forth to the first sort last. Make a loop that is operational
on the reversed sortspec list. Use vl-sort each time through.

Regards,
Doug


"Mike Hutchinson" wrote in message
news:3D5131D9.5491AE63@bbsae.com...
> OK... what I am looking for is that you could pass in lists of vertually any
> size (all the same number of elements of course)
> but mixed types... string integers or reals
> right now the application I have in mind uses 10 elements.
> Then specify in a second parameter list specifiing just how you want it sorted
>
> a little complex but you get the idea ?
> (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2 1)("E"
> "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
>
> (Sorttheselists LstOfLists SortOrderSpec)
>
> what I would want this to do is sort the list
> first by the 2nd element in a ascending order,
> then by the 4th element in a ascending order,
> lastly by the 3rd element in a ascending order.
>
> in any one call the number of sort specs could not exceed the number of
> elements in each list.
> all the lists would have to be the same number of elements.
> all lists would have to be in the same order with regards to data type... (str
> int int real str str)
>
> with the above sort specs the result should be like this...
> (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c" 2 1
> 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
>
> this is quit similar to how excel sort is... (I know I could harness excel to
> do it for me perhaps but I don't have the knowledge to get lisp (or VBA) to do
> it... )
>
> The only other problem this might have in my application is the number of
> lists could be quit large perhaps as many as 100 or more, but probably not as
> many as 500. In my experience older programs using older bubble sort
> functions could error out exceeding the stack (forget what the stack was
> called just now)
>
> anyway... that's it.
>
> Mike Hutchinson wrote:
>
> > OK... let me compile a more complex list and attach it... I'll be back!
> >
> > Mike Hutchinson wrote:
> >
> > > If I want to sort a list of lists... say on the 3rd element of each how
> > > might I go about this?
> > >
> > > The following logic is what I thought of ?
> > >
> > > process the lists moving all the 3rd elements to the head of each list.
> > > extract all the car elements (was the 3rd el) into their own list.
> > > sort this with acad_strlsort if each is a string or with a number
> > > sorting routine if they are integers or reals.
> > > reprocess the original list with a foreach on the sorted car elements
> > > moving them from the origninal lists to a new list.
> > > process the new sorted list moving all the car elements back to the 3rd
> > > position.
> > >
> > > problem...
> > > If I have two or more lists that are similar like
> > >
> > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > >
> > > How can I get them to sort like this:
> > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > >
> > > In this case all three lists have an identical 3rd element, but in each
> > > list the 2nd elements are different.
> > > I suppose I would want them to sort first on the 3rd element then on the
> > > 1rst element.
> > > but how would my application know just how the lists vary or are similar
> > > but not exactly the same.
> > >
> > > Any thougts?
>
Message 9 of 34
Anonymous
in reply to: Anonymous

So a nested vl-sort would be required ?

Doug Broad wrote:

> And what would that be worth to ya? 🙂
> Since you appear to understand how to write the program yourself, perhaps
> a hint will do.
>
> Your sortspec is in order of descending importance so do the last
> sort first and so forth to the first sort last. Make a loop that is operational
> on the reversed sortspec list. Use vl-sort each time through.
>
> Regards,
> Doug
>
> "Mike Hutchinson" wrote in message
> news:3D5131D9.5491AE63@bbsae.com...
> > OK... what I am looking for is that you could pass in lists of vertually any
> > size (all the same number of elements of course)
> > but mixed types... string integers or reals
> > right now the application I have in mind uses 10 elements.
> > Then specify in a second parameter list specifiing just how you want it sorted
> >
> > a little complex but you get the idea ?
> > (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2 1)("E"
> > "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> > (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
> >
> > (Sorttheselists LstOfLists SortOrderSpec)
> >
> > what I would want this to do is sort the list
> > first by the 2nd element in a ascending order,
> > then by the 4th element in a ascending order,
> > lastly by the 3rd element in a ascending order.
> >
> > in any one call the number of sort specs could not exceed the number of
> > elements in each list.
> > all the lists would have to be the same number of elements.
> > all lists would have to be in the same order with regards to data type... (str
> > int int real str str)
> >
> > with the above sort specs the result should be like this...
> > (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c" 2 1
> > 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
> >
> > this is quit similar to how excel sort is... (I know I could harness excel to
> > do it for me perhaps but I don't have the knowledge to get lisp (or VBA) to do
> > it... )
> >
> > The only other problem this might have in my application is the number of
> > lists could be quit large perhaps as many as 100 or more, but probably not as
> > many as 500. In my experience older programs using older bubble sort
> > functions could error out exceeding the stack (forget what the stack was
> > called just now)
> >
> > anyway... that's it.
> >
> > Mike Hutchinson wrote:
> >
> > > OK... let me compile a more complex list and attach it... I'll be back!
> > >
> > > Mike Hutchinson wrote:
> > >
> > > > If I want to sort a list of lists... say on the 3rd element of each how
> > > > might I go about this?
> > > >
> > > > The following logic is what I thought of ?
> > > >
> > > > process the lists moving all the 3rd elements to the head of each list.
> > > > extract all the car elements (was the 3rd el) into their own list.
> > > > sort this with acad_strlsort if each is a string or with a number
> > > > sorting routine if they are integers or reals.
> > > > reprocess the original list with a foreach on the sorted car elements
> > > > moving them from the origninal lists to a new list.
> > > > process the new sorted list moving all the car elements back to the 3rd
> > > > position.
> > > >
> > > > problem...
> > > > If I have two or more lists that are similar like
> > > >
> > > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > > >
> > > > How can I get them to sort like this:
> > > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > > >
> > > > In this case all three lists have an identical 3rd element, but in each
> > > > list the 2nd elements are different.
> > > > I suppose I would want them to sort first on the 3rd element then on the
> > > > 1rst element.
> > > > but how would my application know just how the lists vary or are similar
> > > > but not exactly the same.
> > > >
> > > > Any thougts?
> >
Message 10 of 34
Anonymous
in reply to: Anonymous

Yes. Actually the results you specified would imply that the last
sort was the most importants so you would not reverse the list. Since
you are passing quoted symbols, you would need:

(defun sortlists (lst spec)
(foreach s spec
(setq i (1- (car s)))
(setq lst
(vl-sort
lst
(function
(lambda (a b)
((vl-symbol-value(cdr s)) (nth i a)(nth i b)))))))
lst)

If you passed the operators themselves rather than quoted versions, you
could omit the vl-symbol-value function.

"Mike Hutchinson" wrote in message
news:3D513D1D.93613578@bbsae.com...
> So a nested vl-sort would be required ?

> > Your sortspec is in order of descending importance so do the last
> > sort first and so forth to the first sort last. Make a loop that is operational
> > on the reversed sortspec list. Use vl-sort each time through.
> >
> > Regards,
> > Doug
> >
> > "Mike Hutchinson" wrote in message
> > news:3D5131D9.5491AE63@bbsae.com...
> > > OK... what I am looking for is that you could pass in lists of vertually any
> > > size (all the same number of elements of course)
> > > but mixed types... string integers or reals
> > > right now the application I have in mind uses 10 elements.
> > > Then specify in a second parameter list specifiing just how you want it sorted
> > >
> > > a little complex but you get the idea ?
> > > (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2 1)("E"
> > > "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> > > (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
> > >
> > > (Sorttheselists LstOfLists SortOrderSpec)
> > >
> > > what I would want this to do is sort the list
> > > first by the 2nd element in a ascending order,
> > > then by the 4th element in a ascending order,
> > > lastly by the 3rd element in a ascending order.
> > >
> > > in any one call the number of sort specs could not exceed the number of
> > > elements in each list.
> > > all the lists would have to be the same number of elements.
> > > all lists would have to be in the same order with regards to data type... (str
> > > int int real str str)
> > >
> > > with the above sort specs the result should be like this...
> > > (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c" 2 1
> > > 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
> > >
> > > this is quit similar to how excel sort is... (I know I could harness excel to
> > > do it for me perhaps but I don't have the knowledge to get lisp (or VBA) to do
> > > it... )
> > >
> > > The only other problem this might have in my application is the number of
> > > lists could be quit large perhaps as many as 100 or more, but probably not as
> > > many as 500. In my experience older programs using older bubble sort
> > > functions could error out exceeding the stack (forget what the stack was
> > > called just now)
> > >
> > > anyway... that's it.
> > >
> > > Mike Hutchinson wrote:
> > >
> > > > OK... let me compile a more complex list and attach it... I'll be back!
> > > >
> > > > Mike Hutchinson wrote:
> > > >
> > > > > If I want to sort a list of lists... say on the 3rd element of each how
> > > > > might I go about this?
> > > > >
> > > > > The following logic is what I thought of ?
> > > > >
> > > > > process the lists moving all the 3rd elements to the head of each list.
> > > > > extract all the car elements (was the 3rd el) into their own list.
> > > > > sort this with acad_strlsort if each is a string or with a number
> > > > > sorting routine if they are integers or reals.
> > > > > reprocess the original list with a foreach on the sorted car elements
> > > > > moving them from the origninal lists to a new list.
> > > > > process the new sorted list moving all the car elements back to the 3rd
> > > > > position.
> > > > >
> > > > > problem...
> > > > > If I have two or more lists that are similar like
> > > > >
> > > > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > >
> > > > > How can I get them to sort like this:
> > > > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > > > >
> > > > > In this case all three lists have an identical 3rd element, but in each
> > > > > list the 2nd elements are different.
> > > > > I suppose I would want them to sort first on the 3rd element then on the
> > > > > 1rst element.
> > > > > but how would my application know just how the lists vary or are similar
> > > > > but not exactly the same.
> > > > >
> > > > > Any thougts?
> > >
>
Message 11 of 34
Anonymous
in reply to: Anonymous

Try this:

(setq fuzz 1.0e-4) ;; numeric precision

;; Recursive comparison function:

(defun compare-sub-elements (a b sortspec)
( (lambda (x y test)
(if (and (equal x y fuzz) (cdr sortspec))
(compare-sub-elements a b (cdr sortspec))
(apply test (list x y))
)
)
(nth (cdar sortspec) a)
(nth (cdar sortspec) b)
(caar sortspec)
)
)

;; Main function used in place of vl-sort:

(defun complex-sort (alist sortspec)
(vl-sort alist
'(lambda (a b)
(compare-elements a b sortspec)
)
)
)

;; TEST

(defun C:TESTIT ( / lst)
(setq lst
'( ("D" "a" 3 2 1)
("B" "c" 2 1 3)
("B" "a" 2 1 3)
("D" "b" 3 2 1)
("E" "a" 2 2 1)
("C" "b" 1 3 2)
("D" "b" 0 2 1)
)
)
(mapcar 'print
(complex-sort
lst
'((< . 1) (< . 3) (< . 0)) ; sort specification
)
)
(princ)
)

The "sort specification" has the following form:

(( . ) ...)

Where is a function that compares
two elements (such as > or <), and is
is the 0-based index of the elements of each
sublist to compare using .

There is one dotted pair of .
for each sub-element that you want to sort the
list on.


"Mike Hutchinson" wrote in message
news:3D5131D9.5491AE63@bbsae.com...
> OK... what I am looking for is that you could pass in lists of vertually
any
> size (all the same number of elements of course)
> but mixed types... string integers or reals
> right now the application I have in mind uses 10 elements.
> Then specify in a second parameter list specifiing just how you want it
sorted
>
> a little complex but you get the idea ?
> (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2
1)("E"
> "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
>
> (Sorttheselists LstOfLists SortOrderSpec)
>
> what I would want this to do is sort the list
> first by the 2nd element in a ascending order,
> then by the 4th element in a ascending order,
> lastly by the 3rd element in a ascending order.
>
> in any one call the number of sort specs could not exceed the number of
> elements in each list.
> all the lists would have to be the same number of elements.
> all lists would have to be in the same order with regards to data type...
(str
> int int real str str)
>
> with the above sort specs the result should be like this...
> (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c"
2 1
> 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
>
> this is quit similar to how excel sort is... (I know I could harness excel
to
> do it for me perhaps but I don't have the knowledge to get lisp (or VBA)
to do
> it... )
>
> The only other problem this might have in my application is the number of
> lists could be quit large perhaps as many as 100 or more, but probably not
as
> many as 500. In my experience older programs using older bubble sort
> functions could error out exceeding the stack (forget what the stack was
> called just now)
>
> anyway... that's it.
>
> Mike Hutchinson wrote:
>
> > OK... let me compile a more complex list and attach it... I'll be back!
> >
> > Mike Hutchinson wrote:
> >
> > > If I want to sort a list of lists... say on the 3rd element of each
how
> > > might I go about this?
> > >
> > > The following logic is what I thought of ?
> > >
> > > process the lists moving all the 3rd elements to the head of each
list.
> > > extract all the car elements (was the 3rd el) into their own list.
> > > sort this with acad_strlsort if each is a string or with a number
> > > sorting routine if they are integers or reals.
> > > reprocess the original list with a foreach on the sorted car elements
> > > moving them from the origninal lists to a new list.
> > > process the new sorted list moving all the car elements back to the
3rd
> > > position.
> > >
> > > problem...
> > > If I have two or more lists that are similar like
> > >
> > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > >
> > > How can I get them to sort like this:
> > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > >
> > > In this case all three lists have an identical 3rd element, but in
each
> > > list the 2nd elements are different.
> > > I suppose I would want them to sort first on the 3rd element then on
the
> > > 1rst element.
> > > but how would my application know just how the lists vary or are
similar
> > > but not exactly the same.
> > >
> > > Any thougts?
>
Message 12 of 34
Anonymous
in reply to: Anonymous

Correction:

In the complex-sort function, 'compare-elements'
should be 'compare-sub-elements':

(defun complex-sort (alist sortspec)
(vl-sort alist
'(lambda (a b)
(compare-sub-elements a b sortspec)
)
)
)
Message 13 of 34
Anonymous
in reply to: Anonymous

Bingo!
Do you think this should work on large lists... say a 100 - 200 or so ?
I will set out to test.

Tony Tanzillo wrote:

> Try this:
>
> (setq fuzz 1.0e-4) ;; numeric precision
>
> ;; Recursive comparison function:
>
> (defun compare-sub-elements (a b sortspec)
> ( (lambda (x y test)
> (if (and (equal x y fuzz) (cdr sortspec))
> (compare-sub-elements a b (cdr sortspec))
> (apply test (list x y))
> )
> )
> (nth (cdar sortspec) a)
> (nth (cdar sortspec) b)
> (caar sortspec)
> )
> )
>
> ;; Main function used in place of vl-sort:
>
> (defun complex-sort (alist sortspec)
> (vl-sort alist
> '(lambda (a b)
> (compare-elements a b sortspec)
> )
> )
> )
>
> ;; TEST
>
> (defun C:TESTIT ( / lst)
> (setq lst
> '( ("D" "a" 3 2 1)
> ("B" "c" 2 1 3)
> ("B" "a" 2 1 3)
> ("D" "b" 3 2 1)
> ("E" "a" 2 2 1)
> ("C" "b" 1 3 2)
> ("D" "b" 0 2 1)
> )
> )
> (mapcar 'print
> (complex-sort
> lst
> '((< . 1) (< . 3) (< . 0)) ; sort specification
> )
> )
> (princ)
> )
>
> The "sort specification" has the following form:
>
> (( . ) ...)
>
> Where is a function that compares
> two elements (such as > or <), and is
> is the 0-based index of the elements of each
> sublist to compare using .
>
> There is one dotted pair of .
> for each sub-element that you want to sort the
> list on.
>
> "Mike Hutchinson" wrote in message
> news:3D5131D9.5491AE63@bbsae.com...
> > OK... what I am looking for is that you could pass in lists of vertually
> any
> > size (all the same number of elements of course)
> > but mixed types... string integers or reals
> > right now the application I have in mind uses 10 elements.
> > Then specify in a second parameter list specifiing just how you want it
> sorted
> >
> > a little complex but you get the idea ?
> > (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2
> 1)("E"
> > "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> > (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
> >
> > (Sorttheselists LstOfLists SortOrderSpec)
> >
> > what I would want this to do is sort the list
> > first by the 2nd element in a ascending order,
> > then by the 4th element in a ascending order,
> > lastly by the 3rd element in a ascending order.
> >
> > in any one call the number of sort specs could not exceed the number of
> > elements in each list.
> > all the lists would have to be the same number of elements.
> > all lists would have to be in the same order with regards to data type...
> (str
> > int int real str str)
> >
> > with the above sort specs the result should be like this...
> > (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c"
> 2 1
> > 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
> >
> > this is quit similar to how excel sort is... (I know I could harness excel
> to
> > do it for me perhaps but I don't have the knowledge to get lisp (or VBA)
> to do
> > it... )
> >
> > The only other problem this might have in my application is the number of
> > lists could be quit large perhaps as many as 100 or more, but probably not
> as
> > many as 500. In my experience older programs using older bubble sort
> > functions could error out exceeding the stack (forget what the stack was
> > called just now)
> >
> > anyway... that's it.
> >
> > Mike Hutchinson wrote:
> >
> > > OK... let me compile a more complex list and attach it... I'll be back!
> > >
> > > Mike Hutchinson wrote:
> > >
> > > > If I want to sort a list of lists... say on the 3rd element of each
> how
> > > > might I go about this?
> > > >
> > > > The following logic is what I thought of ?
> > > >
> > > > process the lists moving all the 3rd elements to the head of each
> list.
> > > > extract all the car elements (was the 3rd el) into their own list.
> > > > sort this with acad_strlsort if each is a string or with a number
> > > > sorting routine if they are integers or reals.
> > > > reprocess the original list with a foreach on the sorted car elements
> > > > moving them from the origninal lists to a new list.
> > > > process the new sorted list moving all the car elements back to the
> 3rd
> > > > position.
> > > >
> > > > problem...
> > > > If I have two or more lists that are similar like
> > > >
> > > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > > >
> > > > How can I get them to sort like this:
> > > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > > >
> > > > In this case all three lists have an identical 3rd element, but in
> each
> > > > list the 2nd elements are different.
> > > > I suppose I would want them to sort first on the 3rd element then on
> the
> > > > 1rst element.
> > > > but how would my application know just how the lists vary or are
> similar
> > > > but not exactly the same.
> > > >
> > > > Any thougts?
> >
Message 14 of 34
Anonymous
in reply to: Anonymous

What good is code that only works on limited amounts of data ? 🙂

(of course it will).

"Mike Hutchinson" wrote in message
news:3D514BF0.11EACCD7@bbsae.com...
> Bingo!
> Do you think this should work on large lists... say a 100 - 200 or so ?
> I will set out to test.
>
> Tony Tanzillo wrote:
>
> > Try this:
> >
> > (setq fuzz 1.0e-4) ;; numeric precision
> >
> > ;; Recursive comparison function:
> >
> > (defun compare-sub-elements (a b sortspec)
> > ( (lambda (x y test)
> > (if (and (equal x y fuzz) (cdr sortspec))
> > (compare-sub-elements a b (cdr sortspec))
> > (apply test (list x y))
> > )
> > )
> > (nth (cdar sortspec) a)
> > (nth (cdar sortspec) b)
> > (caar sortspec)
> > )
> > )
> >
> > ;; Main function used in place of vl-sort:
> >
> > (defun complex-sort (alist sortspec)
> > (vl-sort alist
> > '(lambda (a b)
> > (compare-elements a b sortspec)
> > )
> > )
> > )
> >
> > ;; TEST
> >
> > (defun C:TESTIT ( / lst)
> > (setq lst
> > '( ("D" "a" 3 2 1)
> > ("B" "c" 2 1 3)
> > ("B" "a" 2 1 3)
> > ("D" "b" 3 2 1)
> > ("E" "a" 2 2 1)
> > ("C" "b" 1 3 2)
> > ("D" "b" 0 2 1)
> > )
> > )
> > (mapcar 'print
> > (complex-sort
> > lst
> > '((< . 1) (< . 3) (< . 0)) ; sort specification
> > )
> > )
> > (princ)
> > )
> >
> > The "sort specification" has the following form:
> >
> > (( . ) ...)
> >
> > Where is a function that compares
> > two elements (such as > or <), and is
> > is the 0-based index of the elements of each
> > sublist to compare using .
> >
> > There is one dotted pair of .
> > for each sub-element that you want to sort the
> > list on.
> >
> > "Mike Hutchinson" wrote in message
> > news:3D5131D9.5491AE63@bbsae.com...
> > > OK... what I am looking for is that you could pass in lists of
vertually
> > any
> > > size (all the same number of elements of course)
> > > but mixed types... string integers or reals
> > > right now the application I have in mind uses 10 elements.
> > > Then specify in a second parameter list specifiing just how you want
it
> > sorted
> > >
> > > a little complex but you get the idea ?
> > > (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2
> > 1)("E"
> > > "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> > > (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
> > >
> > > (Sorttheselists LstOfLists SortOrderSpec)
> > >
> > > what I would want this to do is sort the list
> > > first by the 2nd element in a ascending order,
> > > then by the 4th element in a ascending order,
> > > lastly by the 3rd element in a ascending order.
> > >
> > > in any one call the number of sort specs could not exceed the number
of
> > > elements in each list.
> > > all the lists would have to be the same number of elements.
> > > all lists would have to be in the same order with regards to data
type...
> > (str
> > > int int real str str)
> > >
> > > with the above sort specs the result should be like this...
> > > (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B"
"c"
> > 2 1
> > > 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
> > >
> > > this is quit similar to how excel sort is... (I know I could harness
excel
> > to
> > > do it for me perhaps but I don't have the knowledge to get lisp (or
VBA)
> > to do
> > > it... )
> > >
> > > The only other problem this might have in my application is the number
of
> > > lists could be quit large perhaps as many as 100 or more, but probably
not
> > as
> > > many as 500. In my experience older programs using older bubble sort
> > > functions could error out exceeding the stack (forget what the stack
was
> > > called just now)
> > >
> > > anyway... that's it.
> > >
> > > Mike Hutchinson wrote:
> > >
> > > > OK... let me compile a more complex list and attach it... I'll be
back!
> > > >
> > > > Mike Hutchinson wrote:
> > > >
> > > > > If I want to sort a list of lists... say on the 3rd element of
each
> > how
> > > > > might I go about this?
> > > > >
> > > > > The following logic is what I thought of ?
> > > > >
> > > > > process the lists moving all the 3rd elements to the head of each
> > list.
> > > > > extract all the car elements (was the 3rd el) into their own
list.
> > > > > sort this with acad_strlsort if each is a string or with a number
> > > > > sorting routine if they are integers or reals.
> > > > > reprocess the original list with a foreach on the sorted car
elements
> > > > > moving them from the origninal lists to a new list.
> > > > > process the new sorted list moving all the car elements back to
the
> > 3rd
> > > > > position.
> > > > >
> > > > > problem...
> > > > > If I have two or more lists that are similar like
> > > > >
> > > > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > >
> > > > > How can I get them to sort like this:
> > > > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > > > >
> > > > > In this case all three lists have an identical 3rd element, but in
> > each
> > > > > list the 2nd elements are different.
> > > > > I suppose I would want them to sort first on the 3rd element then
on
> > the
> > > > > 1rst element.
> > > > > but how would my application know just how the lists vary or are
> > similar
> > > > > but not exactly the same.
> > > > >
> > > > > Any thougts?
> > >
>
Message 15 of 34
Anonymous
in reply to: Anonymous

Use mine if you are worried about stack overflow.
With your data,
(sortlists lst sortorder)
returns:
(("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("B" "c" 2 1 3) ("E" "a" 2 2 1) ("D" "a"
3 2 1) ("D" "b" 3 2 1))

Rewritten to handle arguments Tony's way
(defun srtlists (lst spec)
(foreach s spec
(setq lst
(vl-sort
lst
(function
(lambda (a b)
((vl-symbol-value(car s)) (nth (cdr s) a)(nth (cdr s) b)))))))
lst)

(bench '(srtlists complex-sort) (list lst so) 1000)

SRTLISTS
Elapsed: 2974
Average: 2.9740

COMPLEX-SORT
Elapsed: 6920
Average: 6.9200

(bench '(sortlists) (list lst sortorder) 1000)

SORTLISTS
Elapsed: 2654
Average: 2.6540

Have Fun.

"Mike Hutchinson" wrote in message
news:3D514BF0.11EACCD7@bbsae.com...
> Bingo!
> Do you think this should work on large lists... say a 100 - 200 or so ?
> I will set out to test.
>
> Tony Tanzillo wrote:
>
> > Try this:
> >
> > (setq fuzz 1.0e-4) ;; numeric precision
> >
> > ;; Recursive comparison function:
> >
> > (defun compare-sub-elements (a b sortspec)
> > ( (lambda (x y test)
> > (if (and (equal x y fuzz) (cdr sortspec))
> > (compare-sub-elements a b (cdr sortspec))
> > (apply test (list x y))
> > )
> > )
> > (nth (cdar sortspec) a)
> > (nth (cdar sortspec) b)
> > (caar sortspec)
> > )
> > )
> >
> > ;; Main function used in place of vl-sort:
> >
> > (defun complex-sort (alist sortspec)
> > (vl-sort alist
> > '(lambda (a b)
> > (compare-elements a b sortspec)
> > )
> > )
> > )
> >
> > ;; TEST
> >
> > (defun C:TESTIT ( / lst)
> > (setq lst
> > '( ("D" "a" 3 2 1)
> > ("B" "c" 2 1 3)
> > ("B" "a" 2 1 3)
> > ("D" "b" 3 2 1)
> > ("E" "a" 2 2 1)
> > ("C" "b" 1 3 2)
> > ("D" "b" 0 2 1)
> > )
> > )
> > (mapcar 'print
> > (complex-sort
> > lst
> > '((< . 1) (< . 3) (< . 0)) ; sort specification
> > )
> > )
> > (princ)
> > )
> >
> > The "sort specification" has the following form:
> >
> > (( . ) ...)
> >
> > Where is a function that compares
> > two elements (such as > or <), and is
> > is the 0-based index of the elements of each
> > sublist to compare using .
> >
> > There is one dotted pair of .
> > for each sub-element that you want to sort the
> > list on.
> >
> > "Mike Hutchinson" wrote in message
> > news:3D5131D9.5491AE63@bbsae.com...
> > > OK... what I am looking for is that you could pass in lists of vertually
> > any
> > > size (all the same number of elements of course)
> > > but mixed types... string integers or reals
> > > right now the application I have in mind uses 10 elements.
> > > Then specify in a second parameter list specifiing just how you want it
> > sorted
> > >
> > > a little complex but you get the idea ?
> > > (setq lst '(("D" "a" 3 2 1)("B" "c" 2 1 3)("B" "a" 2 1 3)("D" "b" 3 2
> > 1)("E"
> > > "a" 2 2 1)("C" "b" 1 3 2)("D" "b" 0 2 1)))
> > > (setq sortorder (list (cons 2 '<)(cons 1 '<)(cons 3 '<)...)
> > >
> > > (Sorttheselists LstOfLists SortOrderSpec)
> > >
> > > what I would want this to do is sort the list
> > > first by the 2nd element in a ascending order,
> > > then by the 4th element in a ascending order,
> > > lastly by the 3rd element in a ascending order.
> > >
> > > in any one call the number of sort specs could not exceed the number of
> > > elements in each list.
> > > all the lists would have to be the same number of elements.
> > > all lists would have to be in the same order with regards to data type...
> > (str
> > > int int real str str)
> > >
> > > with the above sort specs the result should be like this...
> > > (("D" "b" 0 2 1) ("C" "b" 1 3 2) ("B" "a" 2 1 3) ("E" "a" 2 2 1) ("B" "c"
> > 2 1
> > > 3) ("D" "a" 3 2 1) ("D" "b" 3 2 1))
> > >
> > > this is quit similar to how excel sort is... (I know I could harness excel
> > to
> > > do it for me perhaps but I don't have the knowledge to get lisp (or VBA)
> > to do
> > > it... )
> > >
> > > The only other problem this might have in my application is the number of
> > > lists could be quit large perhaps as many as 100 or more, but probably not
> > as
> > > many as 500. In my experience older programs using older bubble sort
> > > functions could error out exceeding the stack (forget what the stack was
> > > called just now)
> > >
> > > anyway... that's it.
> > >
> > > Mike Hutchinson wrote:
> > >
> > > > OK... let me compile a more complex list and attach it... I'll be back!
> > > >
> > > > Mike Hutchinson wrote:
> > > >
> > > > > If I want to sort a list of lists... say on the 3rd element of each
> > how
> > > > > might I go about this?
> > > > >
> > > > > The following logic is what I thought of ?
> > > > >
> > > > > process the lists moving all the 3rd elements to the head of each
> > list.
> > > > > extract all the car elements (was the 3rd el) into their own list.
> > > > > sort this with acad_strlsort if each is a string or with a number
> > > > > sorting routine if they are integers or reals.
> > > > > reprocess the original list with a foreach on the sorted car elements
> > > > > moving them from the origninal lists to a new list.
> > > > > process the new sorted list moving all the car elements back to the
> > 3rd
> > > > > position.
> > > > >
> > > > > problem...
> > > > > If I have two or more lists that are similar like
> > > > >
> > > > > (4 "MIKE" "MARY" "BECKY" "ALICE")
> > > > > (4 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (4 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > >
> > > > > How can I get them to sort like this:
> > > > > (3 "MIKE" "ANNA" "BECKY" "ALICE")
> > > > > (3 "MIKE" "BILL" "BECKY" "ALICE")
> > > > > (3 "MIKE" "MARY" "BECKY" "ALICE")
> > > > >
> > > > > In this case all three lists have an identical 3rd element, but in
> > each
> > > > > list the 2nd elements are different.
> > > > > I suppose I would want them to sort first on the 3rd element then on
> > the
> > > > > 1rst element.
> > > > > but how would my application know just how the lists vary or are
> > similar
> > > > > but not exactly the same.
> > > > >
> > > > > Any thougts?
> > >
>
Message 16 of 34
Anonymous
in reply to: Anonymous

"Doug Broad" wrote in message
news:19D486F53900B61070D0A89B30B8ABF2@in.WebX.maYIadrTaRb...
> Use mine if you are worried about stack overflow.

Huh?

What stack overflow?
Message 17 of 34
Anonymous
in reply to: Anonymous

If you're worried about performance, then you would
probably be better off indexing the list rather than
sorting it.

That would allow you to sort the same list in different
ways without duplicating it for each sort criteria.

On a related note, I didn't realize this because my own
(vl-sort) is redefined to not use the built-in visual
LISP (vl-sort) function (for two reasons, one is because
it runs in pre-AutoCAD 2000, and secondly, because vl-sort
removes duplicate elements).

So, if you're using the standard built-in (vl-sort) and
there are duplicate elements in the list, then you need
to use something like this instead:

(defun compare-elements (a b sortspec)
( (lambda (x y test)
(if (and (equal x y fuzz) (cdr sortspec))
(compare-elements a b (cdr sortspec))
(apply test (list x y))
)
)
(nth (cdar sortspec) a)
(nth (cdar sortspec) b)
(caar sortspec)
)
)

(defun complex-sort (alist sortspec)
(mapcar
'(lambda (i)
(nth i alist)
)
(vl-sort-i alist
'(lambda (a b)
(compare-elements a b sortspec)
)
)
)
)

However, why bother sorting the list at all, if you can
just index it (which produces a list of integers that
describe the list in the sorted order), and then just use
the (mapcar '(lambda (i) (nth...))) technique to process
the list in the sorted order.

That would allow you to sort the same list in different
ways without having to replicate the data in the list.



"Mike Hutchinson" wrote in message
news:3D514BF0.11EACCD7@bbsae.com...
> Bingo!
> Do you think this should work on large lists... say a 100 - 200 or so ?
Message 18 of 34
Anonymous
in reply to: Anonymous

Sorry Tony,
It is very very doubtful that "stack overflow" would EVER occur with your code
especially given the arguments anticipated. In the past with recursive
procedures, I have run into the problem of stack overflow. It hasn't
happened to me yet with AC2002 but I have learned to be very careful.
I am sure you know what the term "stack overflow" means but
for the benefit of others reading, I excerpt from the help files:

"A Stack Overflow error sometimes occurs while you
are performing complex operations.

The stack is a special area of memory set aside for tracking program execution.
For example, when a program calls a subroutine, it must first 'push' the position
of the program counter (the memory location of the instruction being executed)
onto the stack so that when it is finished processing that subroutine, it can 'pop'
the program counter back off the stack and continue calling the routine from
where it left off.

Most programming languages also borrow stack space to store parameter
values when passing them to a subroutine. The subroutine will read or modify
these values and when it returns, the calling routine will pop them off to
restore the stack to its original state. Normally, 1 megabyte of space is reserved
for the stack by 32-bit applications, but this is adjustable when building the
application. Sometimes when subroutine calls become too deep or store too
much information, the stack overflows resulting in a Stack Overflow error."

I tried a 6000 element word list with a recursive qsort algorithm and couldn't
get the error so I guess AutoLISP has improved since R14 and earlier.

This VERY VERY POORLY written recursive program will
demonstrate the error however.

(defun badprog (lst)
(while (< (setq trigger (length lst)) 150000)
(badprog (cons "alpha" lst))))

Command: (badprog nil)
Hard error occurred ***
internal stack limit reached (simulated)

Command: !trigger
19996

Regards,
Doug


"Tony Tanzillo" wrote in message
news:4BA35012750A6A5F8076819145869F6B@in.WebX.maYIadrTaRb...
> "Doug Broad" wrote in message
> news:19D486F53900B61070D0A89B30B8ABF2@in.WebX.maYIadrTaRb...
> > Use mine if you are worried about stack overflow.
>
> Huh?
>
> What stack overflow?
>
>
>
>
Message 19 of 34
Anonymous
in reply to: Anonymous

Visual LISP is somewhat different in terms of how it
handles recursion (it's said to be 'properly tail
recursive'), and in fact, you can recurse very deeply
(much more than you could in legacy AutoLISP) without
a stack overflow.

And as you mention, the chances that a routine like
this will ever exhaust the stack are slim-to-none,
since it would require a scenario where the list that
is sorted has elements with hundreds of sub-elements,
and where you are sorting on hundreds of sort keys 🙂

"Doug Broad" wrote in message
news:EC11936A0CE625797D49150E44E6DEAA@in.WebX.maYIadrTaRb...
> Sorry Tony,
> It is very very doubtful that "stack overflow" would EVER occur with your
code
> especially given the arguments anticipated. In the past with recursive
> procedures, I have run into the problem of stack overflow. It hasn't
> happened to me yet with AC2002 but I have learned to be very careful.
> I am sure you know what the term "stack overflow" means but
> for the benefit of others reading, I excerpt from the help files:
>
> "A Stack Overflow error sometimes occurs while you
> are performing complex operations.
>
> The stack is a special area of memory set aside for tracking program
execution.
> For example, when a program calls a subroutine, it must first 'push' the
position
> of the program counter (the memory location of the instruction being
executed)
> onto the stack so that when it is finished processing that subroutine, it
can 'pop'
> the program counter back off the stack and continue calling the routine
from
> where it left off.
>
> Most programming languages also borrow stack space to store parameter
> values when passing them to a subroutine. The subroutine will read or
modify
> these values and when it returns, the calling routine will pop them off
to
> restore the stack to its original state. Normally, 1 megabyte of space is
reserved
> for the stack by 32-bit applications, but this is adjustable when
building the
> application. Sometimes when subroutine calls become too deep or store too
> much information, the stack overflows resulting in a Stack Overflow
error."
>
> I tried a 6000 element word list with a recursive qsort algorithm and
couldn't
> get the error so I guess AutoLISP has improved since R14 and earlier.
>
> This VERY VERY POORLY written recursive program will
> demonstrate the error however.
>
> (defun badprog (lst)
> (while (< (setq trigger (length lst)) 150000)
> (badprog (cons "alpha" lst))))
>
> Command: (badprog nil)
> Hard error occurred ***
> internal stack limit reached (simulated)
>
> Command: !trigger
> 19996
>
> Regards,
> Doug
>
>
> "Tony Tanzillo" wrote in message
> news:4BA35012750A6A5F8076819145869F6B@in.WebX.maYIadrTaRb...
> > "Doug Broad" wrote in message
> > news:19D486F53900B61070D0A89B30B8ABF2@in.WebX.maYIadrTaRb...
> > > Use mine if you are worried about stack overflow.
> >
> > Huh?
> >
> > What stack overflow?
> >
> >
> >
> >
>
>
Message 20 of 34
Anonymous
in reply to: Anonymous

Excellent point about the removal of duplicates. The removal behavior, however,
seems to be limited to lists of integers. It does not occur with lists of strings or
lists
or lists of lists or lists of reals. The behavior is strangely incosistent. Thanks for
the
heads up.

The index method is very intriguing but how would you use the
indexing method to accomplish the multi-stage sort that Mike is thinking about?

Regards,
Doug

"Tony Tanzillo" wrote in message
news:D5A76A4F0BEE0B40156BFE222E88617B@in.WebX.maYIadrTaRb...
> If you're worried about performance, then you would
> probably be better off indexing the list rather than
> sorting it.
>
> That would allow you to sort the same list in different
> ways without duplicating it for each sort criteria.
>
> On a related note, I didn't realize this because my own
> (vl-sort) is redefined to not use the built-in visual
> LISP (vl-sort) function (for two reasons, one is because
> it runs in pre-AutoCAD 2000, and secondly, because vl-sort
> removes duplicate elements).
>
> So, if you're using the standard built-in (vl-sort) and
> there are duplicate elements in the list, then you need
> to use something like this instead:
>
> (defun compare-elements (a b sortspec)
> ( (lambda (x y test)
> (if (and (equal x y fuzz) (cdr sortspec))
> (compare-elements a b (cdr sortspec))
> (apply test (list x y))
> )
> )
> (nth (cdar sortspec) a)
> (nth (cdar sortspec) b)
> (caar sortspec)
> )
> )
>
> (defun complex-sort (alist sortspec)
> (mapcar
> '(lambda (i)
> (nth i alist)
> )
> (vl-sort-i alist
> '(lambda (a b)
> (compare-elements a b sortspec)
> )
> )
> )
> )
>
> However, why bother sorting the list at all, if you can
> just index it (which produces a list of integers that
> describe the list in the sorted order), and then just use
> the (mapcar '(lambda (i) (nth...))) technique to process
> the list in the sorted order.
>
> That would allow you to sort the same list in different
> ways without having to replicate the data in the list.
>
>
>
> "Mike Hutchinson" wrote in message
> news:3D514BF0.11EACCD7@bbsae.com...
> > Bingo!
> > Do you think this should work on large lists... say a 100 - 200 or so ?
>
>
>

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost