* Re: alist and multiple values for one key
2003-01-20 13:03 alist and multiple values for one key Norbert C.
@ 2003-01-20 16:03 ` Friedrich Dominicus
2003-01-20 23:53 ` Hannu Koivisto
2003-01-20 16:07 ` Klaus Berndl
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Friedrich Dominicus @ 2003-01-20 16:03 UTC (permalink / raw)
ncauderan@hotmail.com (Norbert C.) writes:
> Hi,
>
> I would lile to find the "good way" to retrieve multiple values
> for a given key in an alist.
>
> But I didn't find a natural way to do it. For example :
> (setq trees '((pine . cones) (pine . acorns) (oak . acorns) (maple .
> seeds)))
> ==> ((pine . cones) (pine . acorns) (oak . acorns) (maple . seeds))
> (assoc 'pine trees)
That does not work this way. assoc can only be used with a symbol but
if you step into the list you just have other lists.
This code will work for the given data:
(defun collect-if (pred list)
(mapcar #'(lambda (el) (when (funcall pred el) el)) list))
you can call it with
(collect-if #'(lambda (item) (eq (car item) 'pine)) trees)
((pine . cones) (pine . acorns))
Regards
Friedrich
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 16:03 ` Friedrich Dominicus
@ 2003-01-20 23:53 ` Hannu Koivisto
2003-01-21 6:30 ` Friedrich Dominicus
2003-01-21 6:57 ` Friedrich Dominicus
0 siblings, 2 replies; 11+ messages in thread
From: Hannu Koivisto @ 2003-01-20 23:53 UTC (permalink / raw)
Friedrich Dominicus <frido@q-software-solutions.com> writes:
> This code will work for the given data:
> (defun collect-if (pred list)
> (mapcar #'(lambda (el) (when (funcall pred el) el)) list))
>
> you can call it with
> (collect-if #'(lambda (item) (eq (car item) 'pine)) trees)
>
> ((pine . cones) (pine . acorns))
I'm afraid that is not what your example expression evaluates to.
Did you try it? Learn about mapcan if you want to get your code
right using one of the map... functions. Of course, to return
just the values as requested by the OP you will need other changes
as well.
--
Hannu
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 23:53 ` Hannu Koivisto
@ 2003-01-21 6:30 ` Friedrich Dominicus
2003-01-21 6:57 ` Friedrich Dominicus
1 sibling, 0 replies; 11+ messages in thread
From: Friedrich Dominicus @ 2003-01-21 6:30 UTC (permalink / raw)
Hannu Koivisto <azure@iki.fi> writes:
> Friedrich Dominicus <frido@q-software-solutions.com> writes:
>
> > This code will work for the given data:
> > (defun collect-if (pred list)
> > (mapcar #'(lambda (el) (when (funcall pred el) el)) list))
> >
> > you can call it with
> > (collect-if #'(lambda (item) (eq (car item) 'pine)) trees)
> >
> > ((pine . cones) (pine . acorns))
>
> I'm afraid that is not what your example expression evaluates to.
> Did you try it?
Yes I tried it. I can not see why mapcan should be used here. I'm
consing up a list if the predicate function yields true. So mapcar is
the right choice.
What I originally wanted was:
(defun find-all-matching (pred list)
(delete-if #'(lambda (item) (not (funcall pred item))) list))
but that won't work with Emacs Lisp but this will:
(defun find-all-matching (pred list)
(delete-if `(lambda (item) (not (,pred item))) list))
So I suggest you tell me why mapcar is not the proper
function to use.
Regards
Friedrich
> Learn about mapcan
if you want to get your code
> right using one of the map... functions. Of course, to return
> just the values as requested by the OP you will need other changes
> as well.
>
> --
> Hannu
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 23:53 ` Hannu Koivisto
2003-01-21 6:30 ` Friedrich Dominicus
@ 2003-01-21 6:57 ` Friedrich Dominicus
1 sibling, 0 replies; 11+ messages in thread
From: Friedrich Dominicus @ 2003-01-21 6:57 UTC (permalink / raw)
Hannu Koivisto <azure@iki.fi> writes:
> Friedrich Dominicus <frido@q-software-solutions.com> writes:
>
> > This code will work for the given data:
> > (defun collect-if (pred list)
> > (mapcar #'(lambda (el) (when (funcall pred el) el)) list))
> >
> > you can call it with
> > (collect-if #'(lambda (item) (eq (car item) 'pine)) trees)
> >
> > ((pine . cones) (pine . acorns))
>
> I'm afraid that is not what your example expression evaluates to.
> Did you try it?
Yes and unfortunatly did I get those results, which I know now are not
correct after your posting and re-thinking and re-trying it.
However what I wanted to write was
(defun find-all-matching (pred list)
(delete-if (lambda (item) (not (funcall pred item))) list))
But this won't work in Emacs Lisp but this (according to posting some days
ago:
(defun find-all-matching (pred list)
(delete-if `(lambda (item) (not (,pred item))) list))
and indeed with list I got
(setf ttree '((pine . p1) (pine . p2) (oak . p3) (oak . p4) (pine
. p4)))
(find-all-matching #'(lambda (item) (eq (car item) 'pine)) ttree)
((pine . p1) (pine . p2) (pine . p4))
This is what I wanted to get. But it's nevertheless wrong because it
is not what the original author wanted. You are right. He
just wanted the values and there your example with loop works as it
should.
Thanks for pointing that out to me.
Friedrich
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 13:03 alist and multiple values for one key Norbert C.
2003-01-20 16:03 ` Friedrich Dominicus
@ 2003-01-20 16:07 ` Klaus Berndl
2003-01-20 17:18 ` Kai Großjohann
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Klaus Berndl @ 2003-01-20 16:07 UTC (permalink / raw)
On 20 Jan 2003, Norbert C. wrote:
> Hi,
>
> I would lile to find the "good way" to retrieve multiple
values
> for a given key in an alist.
>
> But I didn't find a natural way to do it. For example :
> (setq trees '((pine . cones) (pine . acorns) (oak . acorns) (maple .
> seeds)))
> ==> ((pine . cones) (pine . acorns) (oak . acorns) (maple . seeds))
> (assoc 'pine trees)
> ==> (pine . cones)
>
> What I'd like is something that returns each value associated with
> 'pine.
>
> Any thought ?
Multimaps are unfortunately not build in in Emacs. But you can implement
it
very easy. Here is a first fast hack how you can do it, probably not
robust
and fancy enough but it gives you a first impression:
,----
| ;; a fast hack for a multimap
| (defvar multimap nil)
|
| (defun multimap-add (key value)
| (let ((elem (assoc key multimap)))
| (if elem
| (when (not (member value (cdr elem)))
| (setcdr elem (append (list value) (cdr elem))))
| (setq multimap (cons (list key value) multimap)))
| multimap))
|
| (defun multimap-get (key)
| (interactive "sKey: ")
| (message "%s" (cdr (assoc key multimap))))
|
|
| ;; some tests
| (multimap-add "key1" "value1-1")
| (multimap-add "key1" "value1-2")
| (multimap-add "key2" "value2-1")
| (multimap-add "key2" "value2-2")
| (multimap-add "key2" "value2-3")
| (multimap-add "key3" "value3-3")
`----
Klaus
--
Klaus Berndl mailto: klaus.berndl@sdm.de
sd&m AG http://www.sdm.de
software design & management
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 13:03 alist and multiple values for one key Norbert C.
2003-01-20 16:03 ` Friedrich Dominicus
2003-01-20 16:07 ` Klaus Berndl
@ 2003-01-20 17:18 ` Kai Großjohann
2003-01-20 17:19 ` Kai Großjohann
2003-01-21 10:53 ` Oliver Scholz
4 siblings, 0 replies; 11+ messages in thread
From: Kai Großjohann @ 2003-01-20 17:18 UTC (permalink / raw)
ncauderan@hotmail.com (Norbert C.) writes:
> I would lile to find the "good way" to retrieve multiple values
> for a given key in an alist.
>
> But I didn't find a natural way to do it.
You have to do it manually, I'm afraid.
--
Ambibibentists unite!
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 13:03 alist and multiple values for one key Norbert C.
` (2 preceding siblings ...)
2003-01-20 17:18 ` Kai Großjohann
@ 2003-01-20 17:19 ` Kai Großjohann
2003-01-20 23:45 ` Hannu Koivisto
2003-01-21 10:53 ` Oliver Scholz
4 siblings, 1 reply; 11+ messages in thread
From: Kai Großjohann @ 2003-01-20 17:19 UTC (permalink / raw)
ncauderan@hotmail.com (Norbert C.) writes:
> I would lile to find the "good way" to retrieve multiple values
> for a given key in an alist.
>
> But I didn't find a natural way to do it.
Oh, with (require 'cl), you could do
(remove-if-not (lambda (x) (eq (car x) KEY)) ALIST)
Is that natural? It's short, anyway.
--
Ambibibentists unite!
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 17:19 ` Kai Großjohann
@ 2003-01-20 23:45 ` Hannu Koivisto
0 siblings, 0 replies; 11+ messages in thread
From: Hannu Koivisto @ 2003-01-20 23:45 UTC (permalink / raw)
kai.grossjohann@uni-duisburg.de (Kai Großjohann) writes:
> ncauderan@hotmail.com (Norbert C.) writes:
>
>> I would lile to find the "good way" to retrieve multiple values
>> for a given key in an alist.
>>
>> But I didn't find a natural way to do it.
>
> Oh, with (require 'cl), you could do
>
> (remove-if-not (lambda (x) (eq (car x) KEY)) ALIST)
>
> Is that natural? It's short, anyway.
If all your predicate does is (comparison-function (key-retriever x) key),
you can use the :key and :test{,-not} parameters of plain remove*,
resulting to a still shorter alternative:
(remove* key alist :key #'car :test-not #'eq)
But neither of these retrieve all values for a given key, which is
what the OP wanted. Instead, they evaluate to alists with elements
whose keys match the given key.
So, something like this could be used to do what the OP wanted
(loop is from the cl package as well):
(loop for (key . val) in trees
when (eq 'pine key) collect val)
--
Hannu
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-20 13:03 alist and multiple values for one key Norbert C.
` (3 preceding siblings ...)
2003-01-20 17:19 ` Kai Großjohann
@ 2003-01-21 10:53 ` Oliver Scholz
2003-01-21 11:04 ` David Kastrup
4 siblings, 1 reply; 11+ messages in thread
From: Oliver Scholz @ 2003-01-21 10:53 UTC (permalink / raw)
ncauderan@hotmail.com (Norbert C.) writes:
> Hi,
>
> I would lile to find the "good way" to retrieve multiple values
> for a given key in an alist.
>
> But I didn't find a natural way to do it. For example :
> (setq trees '((pine . cones) (pine . acorns) (oak . acorns) (maple .
> seeds)))
> ==> ((pine . cones) (pine . acorns) (oak . acorns) (maple . seeds))
> (assoc 'pine trees)
> ==> (pine . cones)
>
> What I'd like is something that returns each value associated with
> 'pine.
If I don't want to `(require 'cl)' I use something like this:
(delq nil
(mapcar (lambda (elt)
(if (eq (car elt) 'pine) elt nil))
mtrees))
You see this (delq nil (mapcar ... in Emacs' sources at some places,
too.
Oliver
--
2 Pluviôse an 211 de la Révolution
Liberté, Egalité, Fraternité!
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: alist and multiple values for one key
2003-01-21 10:53 ` Oliver Scholz
@ 2003-01-21 11:04 ` David Kastrup
0 siblings, 0 replies; 11+ messages in thread
From: David Kastrup @ 2003-01-21 11:04 UTC (permalink / raw)
Oliver Scholz <alkibiades@gmx.de> writes:
> ncauderan@hotmail.com (Norbert C.) writes:
>
> > Hi,
> >
> > I would lile to find the "good way" to retrieve multiple values
> > for a given key in an alist.
> >
> > But I didn't find a natural way to do it. For example :
> > (setq trees '((pine . cones) (pine . acorns) (oak . acorns) (maple .
> > seeds)))
> > ==> ((pine . cones) (pine . acorns) (oak . acorns) (maple . seeds))
> > (assoc 'pine trees)
> > ==> (pine . cones)
> >
> > What I'd like is something that returns each value associated with
> > 'pine.
>
> If I don't want to `(require 'cl)' I use something like this:
>
> (delq nil
> (mapcar (lambda (elt)
> (if (eq (car elt) 'pine) elt nil))
> mtrees))
>
> You see this (delq nil (mapcar ... in Emacs' sources at some places,
> too.
How does it benchmark against
(apply #'append (mapcar (lambda (elt) (and (eq (car elt) 'pine) (list
elt)))))
?
The latter has the advantage that you don't rip out elements that
were nil to start with, but only those that don't match the condition.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 11+ messages in thread