Q&A's, tips, howto's
cormullion
Posts: 2038 Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:
Post
by cormullion » Mon Jul 20, 2009 9:19 pm
Given an association list:
Code: Select all
(set 'al '(
("A" 123 "fred" 2)
("B" 234 "jim" 3)
("C" 345 "arthur" 4)
("D" 456 "dave" 5)))
how would I remove the "fred" "jim" "arthur" and "dave" strings? In fact, I don't want to remove them by referring to their content, but by specifying index 2. It doesn't seem to be as easy as it could be. (Or is it?!)
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Mon Jul 20, 2009 11:30 pm
There are two ways to do this. The first method pops from each sub-list and is only possible since v.10.0:
Code: Select all
; remove the element at offset 2 in each sublist
(dotimes (i (length al))
(pop (al i) 2))
al => (("A" 123 2) ("B" 234 3) ("C" 345 4) ("D" 456 5))
The second way treats 'al' as one nested list using two indexes to address the element to be popped from 'al':
Code: Select all
; remove at i 2 of al
(dotimes (i (length al))
(pop al i 2))
; remove at (list i 2) of al
(dotimes (i (length al))
(pop al (list i 2)))
The second time the indexes are in a vector, similar to what 'ref' would return in
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Tue Jul 21, 2009 1:46 am
... and yet another method addressing the sublists as associations:
cormullion
Posts: 2038 Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:
Post
by cormullion » Tue Jul 21, 2009 4:22 pm
cool. thanks! I had been trying replace and set-ref-all - to avoid looping ...
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Tue Jul 21, 2009 5:34 pm
avoid looping ...
you could use 'replace' with 'match':
Code: Select all
(replace '(*) al (append (0 2 $it) (-1 $it)) match)
al => (("A" 123 2) ("B" 234 3) ("C" 345 4) ("D" 456 5))
you could do similar with 'set-ref-all' but I suspect that this is faster. The match expression will match every top-level list in 'al', which are the sub-lists in $it. $it is not writable, so we have to construct the new sublist appending slices.
Likewise you could do:
Code: Select all
(set 'al (map (fn (e) (append (0 2 e) (-1 e))) al))
but I guess your were looking for an in-place replacement.
cormullion
Posts: 2038 Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:
Post
by cormullion » Tue Jul 21, 2009 6:51 pm
Yes, they all work! I like the powerful single line style. The more you look, the more you find:
Code: Select all
(replace '(*) al (list (select $it '(0 1 3))) match)
thanks!
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Tue Jul 21, 2009 7:11 pm
... and you don't need 'list' and the selection indexes don't need to be in a list (but they can be, if you wish):
Code: Select all
(replace '(*) al (select $it 0 1 3) match)
so that is probably the shortest solution, we can come up with.
newdep
Posts: 2038 Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands
Post
by newdep » Tue Jul 21, 2009 7:26 pm
Yes true you have to look because its not that obvious actualy..
something that I would use instantly is a combination of 'map
together with 'pop.. but its not going to work..
but this is..
Code: Select all
(map (fn(x) (replace (x 2) x)) al)
is a short solution and returns the result but its a non-destructive solution..
-- (define? (Cornflakes))
newdep
Posts: 2038 Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands
Post
by newdep » Tue Jul 21, 2009 7:38 pm
oke oke and there is the good old loop (hello python)
Code: Select all
(for (x 0 (dec (length al))) (pop (al x) 2) )
probably the fastest..
-- (define? (Cornflakes))
Lutz
Posts: 5289 Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:
Post
by Lutz » Tue Jul 21, 2009 7:54 pm
but we had a better one like this already (first solution in this thread):
Code: Select all
(dotimes (i (length al))
(pop (al i) 2))