0

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: 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?

Community
  • 1
  • 1
greye
  • 8,921
  • 12
  • 41
  • 46
  • 1
    Isn't this the *same* as the previous question you asked, but with ints instead of strings? Doesn't Richie Hindle's answer work? – Dominic Rodger Jan 11 '10 at 06:35
  • Before I wanted to know if an item existed. Now I want to know where it is. Regardless of being ints or strings. – greye Jan 11 '10 at 06:38

5 Answers5

5
[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.

Ofri Raviv
  • 24,375
  • 3
  • 55
  • 55
  • If you are running this code several times, you should use Michael Anderson's solution so that you don't have to traverse the entire list every time. – Miles Jan 11 '10 at 09:10
4

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
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
2

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.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
  • Incidentally, I followed the specs from the question, so the above code produces the index / indices of elements matching certain criteria... It's trivial to change it to return the elements themselves, though, or perhaps `(index, element)` pairs. – Michał Marczyk Jan 11 '10 at 07:43
2

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]
sharjeel
  • 5,825
  • 7
  • 34
  • 49
1

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]
Tendayi Mawushe
  • 25,562
  • 6
  • 51
  • 57