Retrieving a specific object from a list?

andrew cooke andrew at acooke.org
Thu Apr 9 07:16:01 EDT 2009


Jeremiah Dodds wrote:
> I've been looking over some of my code, and I've found something I do that
> has a bit of a smell to it. I've searched the group and docs, and haven't
> found much of anything that solves this particular problem, although I may
> just not be searching correctly.
>
> Anyhow, I find that often I'll have a list of objects of some sort that I
> want to operate on. Most of the time, I'll want to operate on the entire
> list, but sometimes I'll want to operate on just one element, or retrieve
> just one element, and I end up with code something like the following:
>
> items = [Foo(), Foo(), ... Foo()]
>
> a_item = [x for x in items if x.bar == some_value][0]
> another_item = [x for x in items if x.baz == some_other_value][0]
>
> This doesn't seem correct at all, looping over the entire list to create a
> list of one element and then pulling that item out. Any advice?

[some/all of this may be obvious, but since you asked...]

i think the most common solution (at least in my code) is to use a dict
and store the data as a map from value to instance.  you can still operate
on all the instances via .values(), but you also have O(1) access via the
key.

another approach is to use a sorted list.  then you can access things via
the bisect module in O(log(n)) time.

related to sorted lists, you may be able to reframe the algorithm as
something that operates on a queue or stack (if your "some_value" is to
find the "next" item according to an order that is fixed by earlier
processing).  in that case you want deque from collections.

but when you need to access instances by more than one value (.bar and
.baz) then typically that's a hard problem, and there's a trade-off
somewhere.  you might find writing a special container that contains two
dicts is useful.  if so, you might want to use weak references - see
weakref module).

all the above are relatively direct solutions.  in my experience this kind
of issue often comes from not thinking at a high enough level about the
algorithm - even though my third suggestion (deque) sounds rather obscure
you may find that once you look at you algorithm more carefully it can be
rewritten in that way.  i think i've seen this in my own code as i improve
at integrating what might be more "functional" idioms into python in a
"natural" (pythonic) way.

andrew





More information about the Python-list mailing list