I have a tuple of Control
values and I want to find the one with a matching name. Right now I use this:
listView
for control in controls:
if control.name == "ListView":
listView = control
Can I do it simpler than this? Perhaps something like:
listView = controls.FirstOrDefault(c => c.name == "ListView")
Find the index of an element in tuple using index() Tuple provides a member function index() i.e. It returns the index for first occurrence of x in the tuple. Also, if element is not found in tuple then it will throw an exception ValueError.
Tuples are immutable, and usually contain a heterogeneous sequence of elements that are accessed via unpacking or indexing (or even by attribute in the case of namedtuples ). Lists are mutable, and their elements are usually homogeneous and are accessed by iterating over the list.
Here is one option:
listView = next(c for c in controls if c.name == "ListView")
Note that this will raise a StopIteration
if no matching item exists, so you will need to put this in a try/except and replace it with a default if you get a StopIteration
.
Alternatively you can add your default value to the iterable so the next
call always succeeds.
from itertools import chain
listView = next(chain((c for c in controls if c.name == "ListView"), [default])
If you are using Python 2.5 or lower change the call from next(iterable)
to iterable.next()
.
Out of sheer curiosity, I integrated my own answer with your original code and F.J.'s solutions to make a comparative performance test.
It seems that your solution is the fastest of them all. My solution check all possible elements of the controls tuple, so it will be slower as the size of the tuple increases.
Here is the code:
from timeit import Timer as T
from itertools import chain, dropwhile
class control(object):
def __init__(self, name):
self.name = name
def johan_venge(tuple_):
for el in tuple_:
if el.name == 'foobar':
return el
return None
def mac(tuple_):
return filter(lambda x : x.name == 'foobar', tuple_)[0]
def mac2(tuple_):
return list(dropwhile(lambda x : x.name != 'foobar', tuple_))[0]
def fj(tuple_):
return next(c for c in tuple_ if c.name == 'foobar')
def fj2(tuple_):
return next(chain((c for c in tuple_ if c.name == 'foobar')))
if __name__ == '__main__':
REPS = 10000
controls = (control('hello'), control('world'), control('foobar'))
print T(lambda : johan_venge(controls)).repeat(number = REPS)
print T(lambda : mac(controls)).repeat(number = REPS)
print T(lambda : mac2(controls)).repeat(number = REPS)
print T(lambda : fj(controls)).repeat(number = REPS)
print T(lambda : fj2(controls)).repeat(number = REPS)
and here is the output on my system:
[0.005961179733276367, 0.005975961685180664, 0.005918025970458984]
[0.013427019119262695, 0.013586044311523438, 0.013450145721435547]
[0.024325847625732422, 0.0254058837890625, 0.02396702766418457]
[0.014491081237792969, 0.01442408561706543, 0.01484990119934082]
[0.01691603660583496, 0.016616106033325195, 0.016437053680419922]
HTH! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With