开发者

Index of item in list when only part of the item is known

This is a follow-up on a previous question of mine regarding searching in lists of lists

I have a list with pairs of values as lists in it.

[['a',5], ['b',3], ['c',2] ]

I know the first element of each pair but I don't know the second (it's the result of a calculation and stored in the list with the first element. I sorted the list in descending order of the calculated item.

I want to know in which position each of the items is, which would normally be: list.index('a') if I didn't have the numbers there. Is there a way to get the index number without knowing the entirety of the element?

Something like: 开发者_Go百科list.index(['a',?]) where ? is a wildcard?

Or should I just create a new list from the ordered one with just the first item in order to get it's index?


[x[0] for x in list].index('a')

But if you are running this code several times, you might want to save the list of x[0]'s.


There's a similar solution to that of Ofris

D = dict([ [x[1][0],  x[0] ] for x in list(enumerate(L)) ])
D['a']
#returns 0

But another nice feature is that if you tweak this a little you can pull out your original values

D = dict([ [x[1][0],  (x[0], x[1][1] ) ] for x in list(enumerate(L)) ])
D['a'][0]
#returns 0
D['a'][1]
#returns 5


You already have the original list from which you know the first elements. List call it orig_list. Get the element's index from the original list and use that index in the new list to retrieve.

>>> orig_list = ['a','b','c']
>>> calc_list = [['a',5], ['b',3], ['c',2] ]

>>> calc_list[orig_list.index('a')]
['a',5]


A simple, flexible one line version:

[i for (i, item) in enumerate([('a', 1), ('b', 3), ('a', 5)]) if item[0] == 'a']
# returns [0, 2]

[i for (i, item) in enumerate([('a', 1), ('b', 3), ('a', 5)]) if item[0] == 'a'][0]
# returns 0

You could wrap it in a function, replace item[0] == 'a' with a call to an arbitrary predicate (like in my original answer; that's where it's flexible) etc. The second version above will throw an exception if no item is found, so wrap it in try/except; the first one will return an empty list.


If you prefer a separate function for the job, check out the one below... It has the benefit of only consuming as much of your iterable as needed to find an appropriate item.

Original answer:

This will allow you to find the index of the first item possessing any property you can think of, though you'll need to express it as a function (a lambda x: x[0] == 'a' suffices in your example case):

def index_by(pred, iterable):
    i = 0
    found = False
    for item in iterable:
        if pred(item):
            found = True
            break
        i += 1
    return i if found else None

Call like so:

index_by(lambda x: x[0] == 'a', [('b', 1), ('a', 5)]) # returns 1

to obtain the zero-based index of the first item in the iterable which satisfies the given predicate. (In other words, the first item in the iterable passed in as the second argument for which the function passed in as the first argument returns a true value.)

If the iterable does not contain an element satisfying the predicate, None is returned.


The code below will get the indexes of all items in the list that match the pattern ['a', ?]:

>>> l = [['a',5], ['b',3], ['c',2], ['a',8]]
>>> indexes = [l.index(x) for x in l if x[0] == 'a']
>>> print indexes
[0, 3]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜