Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Recipe 4.15. Associating Multiple Values with Each Key in a Dictionary


Credit: Michael Chermside


Problem


You need a dictionary that
maps each key to multiple values.


Solution


By nature, a dictionary is a one-to-one mapping, but
it's not hard to make it one-to-manyin other
words, to make one key map to multiple values. Your choice of one of
two possible approaches depends on how you want to treat duplications
in the set of values for a key. The following approach, based on
using lists as the
dict's values, allows such
duplications:

d1 = {  }
d.setdefault(key, [ ]).append(value)

while an alternative approach, based on using
sub-dicts as the
dict's values, automatically
eliminates duplications of values:

d2 = {  }
d2.setdefault(key, { })[value] = 1

In Python 2.4, the no-duplication approach can equivalently be coded:

d3 = {  }
d3.setdefault(key, set( )).add(value)


Discussion


A normal dictionary performs a simple mapping of each key to one
value. This recipe shows three easy, efficient ways to achieve a
mapping of each key to multiple values, by holding as the
dictionary's values lists,
sub-dicts, or, in Python 2.4,
sets. The semantics of the list-based approach
differ slightly but importantly from those of the other two in terms
of how they deal with duplication. Each approach relies on the
setdefault method of a dictionary, covered earlier
in Recipe 4.10, to
initialize the entry for a key in the dictionary, if needed, and in
any case to return said entry.

You need to be able to do more than just add values for a key. With
the first approach, which uses lists and allows duplications,
here's how to retrieve the list of values for a key:

list_of_values = d1[key]

Here's how to remove one value for a key, if you
don't mind leaving empty lists as items of
d1 when the last value for a key is removed:

d1[key].remove(value)

Despite the empty lists, it's still easy to test for
the existence of a key with at least one valuejust use a
function that always returns a list (maybe an empty one), such as:

def get_values_if_any(d, key):
return d.get(key, [ ])

For example, to check whether 'freep' is
among the values (if any) for key
'somekey' in dictionary
d1, you can code: if 'freep' in
get_values_if_any(d1, 'somekey')
.

The second approach, which uses sub-dicts and
eliminates duplications, can use rather similar idioms. To retrieve
the list of values for a key:

list_of_values = list(d2[key])

To remove one value for a key, leaving empty dictionaries as items of
d2 when the last value for a key is
removed:

del d2[key][value]

In the third approach, showing the Python 2.4-only version
d3, which uses sets,
this would be:

d3[key].remove(value)

One possibility for the get_values_if_any function
in either the second or third (duplication-removing) approaches would
be:

def get_values_if_any(d, key):
return list(d.get(key, ( )))

This recipe focuses on how to code the raw functionality, but, to use
this functionality in a systematic way, you'll
probably want to wrap up this code into a class. For that purpose,
you need to make some of the design decisions that this recipe
highlights. Do you want a value to be in the entry for a key multiple
times? (Is the entry for each key a bag rather than a set, in
mathematical terms?) If so, should remove just
reduce the number of occurrences by 1, or should it wipe out all of
them? This is just the beginning of the choices you have to make, and
the right choices depend on the specifics of your application.


See Also


Recipe 4.10; the
Library Reference and Python in a
Nutshell
sections on mapping types; Recipe 18.8 for an implementation of the
bag type.


/ 394