Use enumerate:
In [3]: user_details = [{'name':x, 'rank':i} for i,x in enumerate(ranked_users)]
In [4]: user_details
Out[4]:
[{'name': 'jon', 'rank': 0},
{'name': 'bob', 'rank': 1},
{'name': 'jane', 'rank': 2},
{'name': 'alice', 'rank': 3},
{'name': 'chris', 'rank': 4}]
PS. My first answer was
user_details = map(lambda (i,x): {'name':x, 'rank':i}, enumerate(ranked_users))
I'd strongly recommend using a list comprehension or generator expression over map and lambda whenever possible. List comprehensions are more readable, and tend to be faster to boot.
Use enumerate:
In [3]: user_details = [{'name':x, 'rank':i} for i,x in enumerate(ranked_users)]
In [4]: user_details
Out[4]:
[{'name': 'jon', 'rank': 0},
{'name': 'bob', 'rank': 1},
{'name': 'jane', 'rank': 2},
{'name': 'alice', 'rank': 3},
{'name': 'chris', 'rank': 4}]
PS. My first answer was
user_details = map(lambda (i,x): {'name':x, 'rank':i}, enumerate(ranked_users))
I'd strongly recommend using a list comprehension or generator expression over map and lambda whenever possible. List comprehensions are more readable, and tend to be faster to boot.
Alternatively you could use a list comprehension rather than map() and lambda.
ranked_users = ['jon','bob','jane','alice','chris']
user_details = [{'name' : x, 'rank' : ranked_users.index(x)} for x in ranked_users]
Output:
[{'name': 'jon', 'rank': 0}, {'name': 'bob', 'rank': 1}, {'name': 'jane', 'rank': 2}, {'name': 'alice', 'rank': 3}, {'name': 'chris', 'rank': 4}]
List comprehensions are very powerful and are also faster than a combination of map and lambda.
[aws-lambda-python] Unify `entry` field betwen aws-lambda-nodejs and aws-lambda-python
python - Return the index of the first element of a list which makes a passed function true - Stack Overflow
python - How to use git with lambda function - Stack Overflow
indexing - How to make an index static for a python lambda expression - Stack Overflow
Videos
You could do that in a one-liner using generators:
next(i for i,v in enumerate(l) if is_odd(v))
The nice thing about generators is that they only compute up to the requested amount. So requesting the first two indices is (almost) just as easy:
y = (i for i,v in enumerate(l) if is_odd(v))
x1 = next(y)
x2 = next(y)
Though, expect a StopIteration exception after the last index (that is how generators work). This is also convenient in your "take-first" approach, to know that no such value was found --- the list.index() function would raise ValueError here.
One possibility is the built-in enumerate function:
def index_of_first(lst, pred):
for i, v in enumerate(lst):
if pred(v):
return i
return None
It's typical to refer a function like the one you describe as a "predicate"; it returns true or false for some question. That's why I call it pred in my example.
I also think it would be better form to return None, since that's the real answer to the question. The caller can choose to explode on None, if required.
Python's closures are late binding. This means that the values of variables used in closures are looked up at the time the function is called.
To avoid the late binding effect you can use a lambda with a default arg:
index = 1
test = lambda t, index=index: t[index]+1 # binds index at definition time
index = 0
print(test([5, 0])) # 1
index is neither an argument nor a local variable in test() so it is indeed resolved as a a nonlocal (+> it's looked up in the enclosing scopes).
The simple solution is to make index an argument of test with a default value capturing the value of index at definition time:
index = 1
test = lambda t, _index=index: t[_index]+1
index = 0
print(test([5, 0]))