all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* alist and multiple values for one key
@ 2003-01-20 13:03 Norbert C.
  2003-01-20 16:03 ` Friedrich Dominicus
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Norbert C. @ 2003-01-20 13:03 UTC (permalink / raw)


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 ?

Thank you,

Norbert

^ 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 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 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 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.
                   ` (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

end of thread, other threads:[~2003-01-21 11:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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-21  6:30     ` Friedrich Dominicus
2003-01-21  6:57     ` 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-20 23:45   ` Hannu Koivisto
2003-01-21 10:53 ` Oliver Scholz
2003-01-21 11:04   ` David Kastrup

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.