Page 1 of 1

Request for deselect function

Posted: Thu Nov 19, 2009 9:14 am
by TedWalther
The select function lets me pick various values from a list to form a new list.

Could we have the corollary as a built in? deselect would return the whole list but WITHOUT the listed items.

Code: Select all

(setq a '(1 2 3 4 5))

(select a 1 2 3) => (2 3 4)
(deselect a 1 2 3) => (1 5)

Re: Request for deselect function

Posted: Thu Nov 19, 2009 12:15 pm
by Lutz
depending on the application you could use difference:

Code: Select all

> (setq a '( 1 2 3 4 5))
(1 2 3 4 5)
> (difference a (select a 1 2 3))
(1 5)
> 
it is not always the same as a deselect, but in this case it is. Nobody has ever asked for this before - what would you use it for?

Re: Request for deselect function

Posted: Thu Nov 19, 2009 10:18 pm
by TedWalther
I'm trying to merge sublists of a list that share common elements. Its a good little puzzle. Because every time I merge two lists, now I have to go back and start at the beginning with the comparisons, because the left hand side is a new and different set of elements.

So, for instance, if I'm iterating over a list, and comparing every element with every other element, I'd do like this:

Code: Select all

(dolist (x lst)
  (filter (fn (y) (= x y)) (deselect lst $idx)))
I do this sort of thing when generating all possible poker hands, and also I'm consolidating Strong's numbers from some XML I have to reduce the 8000 numbers to 6000 numbers.

Ted

Re: Request for deselect function

Posted: Fri Nov 20, 2009 10:59 am
by Kazimir Majorinc
If I understood you well, difference could be pushed one level inside something like:

(set 'a '(101 102 103 104 105))
(select a (difference (sequence 0 (length a)) '(0 1 3 5))) => (103 105)


I said something like, because select has bit strange behaviour which might be bug or not. Dependently on that, (sequence 0 (length a)) might be adjusted.

> (select '(100 101 102) '(1))
(101)
> (select '(100 101 102) '(2))
(102)
> (select '(100 101 102) '(3))
(102)
> (select '(100 101 102) '(4))
(102)
> (select '(100 101 102) '(7))
(102)

>

The way you use deselect, it looks to me like pop, with difference that pop is destructive, while select, filter, clean are not - but it could be combined with copy for your purpose. For very example you shown, i.e. removing duplicated from list, Newlisp has function unique, but for more general problems, I sometimes use dummy variables and make changes "in site", and consolidate the list later. Brute, but simple. Like making checks on grocery list.

Code: Select all

(set 'L '(1 2 9 3 4 5 4 3 2 6 1 2 4))

(dolist(j L)
  (set 'jdx $idx)
  (dolist(i L)
    (when (and (> $idx jdx) (= i j)) 
          (setf (L $idx) 'for-deletition))))

(set 'L (clean (lambda(x)(= x 'for-deletition)) L))

(println L)
(exit)
But - all at all, your request for deselect has sense - I mean, if there is a pair (clean, filter) then why not (select, deselect)?[/color]

Re: Request for deselect function

Posted: Sat Nov 21, 2009 8:43 am
by TedWalther
You are right Kazimir, deselect would be like pop+copy, but it would be a nice shorthand instead of having to do a sequence of pop+copy; sometimes the list to be deselected is the result of a series of calculations, and would allow me to avoid a let-block. And you are also right, it seems to fit with the clean/filter paradigm.