In the following Python script where "aDict" is a dictionary, what does "_: _[0]" do in the lambda function?
sorted(aDict.items(), key=lambda _: _[0])
Lets pick that apart.
1) Suppose you have a dict, di:
di={'one': 1, 'two': 2, 'three': 3}
2) Now suppose you want each of its key, value pairs:
>>> di.items()
[('three', 3), ('two', 2), ('one', 1)]
3) Now you want to sort them (since dicts are unordered):
>>> sorted(di.items())
[('one', 1), ('three', 3), ('two', 2)]
Notice that the tuples are sorted lexicographically -- by the text in the first element of the tuple. This is a equivalent to the t[0] of a series of tuples.
Suppose you wanted it sorted by the number instead. You would you use a key function:
>>> sorted(di.items(), key=lambda t: t[1])
[('one', 1), ('two', 2), ('three', 3)]
The statement you have sorted(aDict.items(), key=lambda _: _[0]) is just using _ as a variable name. It also does nothing, since aDict.items() produces tuples and if you did not use a key it sorts by the first element of the tuple anyway. The key function in your example is completely useless.
There might be a use case for the form (other than for tuples) to consider. If you had strings instead, then you would be sorting by the first character and ignoring the rest:
>>> li=['car','auto','aardvark', 'arizona']
>>> sorted(li, key=lambda c:c[0])
['auto', 'aardvark', 'arizona', 'car']
Vs:
>>> sorted(li)
['aardvark', 'arizona', 'auto', 'car']
I still would not use _ in the lambda however. The use of _ is for a throway variable that has minimal chance of side-effects. Python has namespaces that mostly makes that worry not a real worry.
Consider:
>>> c=22
>>> sorted(li, key=lambda c:c[0])
['auto', 'aardvark', 'arizona', 'car']
>>> c
22
The value of c is preserved because of the local namespace inside the lambda.
However (under Python 2.x but not Python 3.x) this can be a problem:
>>> c=22
>>> [c for c in '123']
['1', '2', '3']
>>> c
'3'
So the (light) convention became using _ for a variable either in the case of a list comprehension or a tuple expansion, etc where you worry less about trampling on one of your names. The message is: If it is named _, I don't really care about it except right here...
In Python _ (underscore) is a valid identifier and can be used as a variable name, e.g.
>>> _ = 10
>>> print(_)
10
It can therefore also be used as the name of an argument to a lambda expression - which is like an unnamed function.
In your example sorted() passes tuples produced by aDict.items() to its key function. The key function returns the first element of that tuple which sorted() then uses as the key, i.e that value to be compared with other values to determine the order.
Note that, in this case, the same result can be produced without a key function because tuples are naturally sorted according to the first element, then the second element, etc. So
sorted(aDict.items())
will produce the same result. Because dictionaries can not contain duplicate keys, the first element of each tuple is unique, so the second element is never considered when sorting.
In Python, lambda is used to create an anonymous function. The first underscore in your example is simply the argument to the lambda function. After the colon (i.e. function signature), the _[0] retrieves the first element of the variable _.
Admittedly, this can be confusing; the lambda component of your example could be re-written as lambda x: x[0] with the same result. Conventionally, though, underscore variable names in Python are used for "throwaway variables". In this case, it implies that the only thing we care about in each dictionary item is the key. Nuanced to a fault, perhaps.
Related
I am having list of tuple from which I want the tuple with the minimum value at index 1. For example, if my list is like:
a =[('a', 2), ('ee', 3), ('mm', 4), ('x', 1)]
I want the returned tuple to be ('x', 1).
Currently I am using sorted function to get this result like:
min=sorted(a, key=lambda t: t[1])[0]
Is there better ways to do it? Maybe with min function?
You may use min() function with key parameter in order to find the tuple with minimum value in the list. There is no need to sort the list. Hence, your min call should be like:
>>> min(a, key=lambda t: t[1])
('x', 1)
Even better to use operator.itemgetter() instead of lambda expression; as itemgetter are comparatively faster. In this case, the call to min function should be like:
>>> from operator import itemgetter
>>> min(a, key=itemgetter(1))
('x', 1)
Note: min() is a in-built function in Python. You should not be using it as a variable name.
This will also work:
min([x[::-1] for x in a])[::-1]
# ('x', 1)
def rearrangelist(list):
lst = input["list"]
lst = ['list'[0]:1,'list'[1]:0,'list'[2]:3];
print (sorted(list))
How can I make this work without using lambda, once I basically want the list elements to be rearrange according to the number that each list element gets defined, per example:
list = [john, peter, olive]
john[2], peter [1] and olive[0]
And I want this to be sorted according to the number printing this:
olive, peter, john
Can´t use "Zip()" function
The easiest solution is to use the operator.itemgetter function
from operator import itemgetter
print(sorted(list, key=itemgetter(1)))
By the way, list is a terrible name for a variable, as it will shadow the list type.
You can use the decorate-sort-undecorate idiom:
>>> names = ['john', 'peter', 'olive']
>>> order = [2, 1, 0]
>>> decorated = zip(order, names)
>>> decorated
[(2, 'john'), (1, 'peter'), (0, 'olive')]
>>> sorted_decorated = sorted(decorated)
>>> sorted_decorated
[(0, 'olive'), (1, 'peter'), (2, 'john')]
>>> undecorated = zip(*sorted_decorated)[1]
>>> undecorated
('olive', 'peter', 'john')
If you can't use zip:
>>> decorated = [(order[index], names[index]) for index in range(len(order))]
And:
>>> undecorated = [value[1] for value in decorated_sorted]
sorted(iterable[, cmp[, key[, reverse]]])
Return a new sorted list from the items in iterable.
The optional arguments cmp, key, and reverse have the same meaning as those for the list.sort() method.
key specifies a function of one argument that is used to extract a comparison key from each list element: key=str.lower. The default value is None (compare the elements directly).
key is what you need. Supply it a function that will return a comparison key
def SortBySecondElement(Element):
return Element[1]
Call sorted method this way
sorted(list, key=SortBySecondElement)
I hope that is what you want.
I have an interview recently. The interviewer asked me the ways to iterate dict in python. I said all the ways use for statement. But he told me that how about lambda?
I feel confused very much and I consider lambda as an anonymity function, but how it iterates a dict? some code like this:
new_dict = sorted(old_dict.items(), lambda x: x[1]) # sorted by value in dict
But in this code, the lambda is used as a function to provide the compared key. What do you think this question?
You don't iterate with lambda. There are following ways to iterate an iterable object in Python:
for statement (your answer)
Comprehension, including list [x for x in y], dictionary {key: value for key, value in x} and set {x for x in y}
Generator expression: (x for x in y)
Pass to function that will iterate it (map, all, itertools module)
Manually call next function until StopIteration happens.
Note: 3 will not iterate it unless you iterate over that generator later. In case of 4 it depends on function.
For iterating specific collections like dict or list there can be more techniques like while col: remove element or with index slicing tricks.
Now lambda comes into the picture. You can use lambdas in some of those functions, for example: map(lambda x: x*2, [1, 2, 3]). But lambda here has nothing to do with iteration process itself, you can pass a regular function map(func, [1, 2, 3]).
You can iterate dict using lambda like this:
d = {'a': 1, 'b': 2}
values = map(lambda key: d[key], d.keys())
Using a plain lambda to iterate anything in Python sounds very wrong. Certainly the most Pythonic method to iterate sequences and collections is to use list comprehensions and generator expressions like #Andrey presented.
If the interviewer was leaning on the more theoretical/Computer Sciencey answers, it is worth noting that using lambdas to iterate is quite possible, although I must stress that this is not Pythonic nor useful at any context other than academic exercises:
# the legendary Y combinator makes it possible
# to let nameless functions recurse using an indirection
Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
# our iterator lambda
it = lambda f: lambda Lst: (Lst[0], f(Lst[1:])) if Lst else None
# see it in action:
Y(it)([1,2,3])
=> (1, (2, (3, None)))
lambda itself doesn't iterate anything. As you thought, it just defines an anonymous function - aside from the syntactic rule about only being able to have an expression, a lambda does nothing more than a similar function made using def. The code inside the lambda might iterate something, but only in the same ways as any other function might use (provided they are expressions, and so valid inside a lambda).
In the example you mention using sorted, the key function is called on each element of the list being sorted - but it is sorted itself that does this, and which does the iteration. When you provide a key function, sorted does something broadly similar to this:
def sorted(seq, key):
decorated = [(key(elem), i) for i, elem in enumerate(seq)]
# Sort using the normal tuple lexicographic comparisons
decorated.sort()
return [seq[i] for _,i in decorated]
As you can see, sorted does the iteration here, not the lambda. Indeed, there is no reason why the key has to be a lambda - any function (or any callable) will do as far as sorted is concerned.
At the lowest level, there is only really one way to iterate a dict (or, indeed, any other iterable) in Python, which is to use the iterator protocol. This is what the for loop does behind the scenes, and you could also use a while statement like this:
it = iter(my_iterable)
while True:
try:
val = next(it)
except StopIteration:
# Run else clause of for loop
break
else:
# Run for loop body
The comments in this aren't strictly part of the iterator protocol, they are instead part of the for loop (but having at least a loop body in there is mostly the point of iterating in the first place).
Other functions and syntax that consume iterables (such as list, set and dict comprehensions, generator expressions or builtins like sum, sorted or max) all use this protocol, by either:
Using a Python for loop,
Doing something like the above while loop (especially for modules written in C),
Delegating to another function or piece of syntax that uses one of these
A class can be made so that its instances become iterable in either of two ways:
Provide the iterator protocol directly. You need a method called __iter__ (called by iter), which returns an iterator. That iterator has a method called __next__ (just next in Python 2) which is called by next and returns the value at the iterator's current location and advances it (or raises StopIteration if it is already at the end); or
Implement part of the sequence protocol (which means behaving like a list or tuple). For forward iteration, it is sufficient to define __getitem__ in such a way that doing my_sequence[0], my_sequence[1], up until my_sequence[n-1] (where n is the number of items in the sequence), and higher indexes raise an error. You usually want to define __len__ as well, which is used when you do len(my_sequence).
Dictionary iteration using lambda
dct = {1: '1', 2 : '2'}
Iterating over Dictionary using lambda:
map(lambda x : str(x[0]) + x[1], dct.iteritems())
here x[0] is the key
and x[1] is the value
Result :
['11', '22']
Filtering on Dictionary using lambda:
filter(lambda x : x[0] > 1, dct.iteritems())
Result :
[(2, '2')]
The best way to iterate dict in python is:
dic ={}
iter_dic = dic.iteritems().next
iter_dic()
...
iter_dic()
But you can build it with lambda func:
iter_dic = lambda dic: dic.keys()[0],dic.pop(dic.keys()[0])
iter_dic(dic)
...
iter_dic(dic)
Could we say
count = {8: 'u', 4: 't', 9: 'z', 10: 'j', 5: 'k', 3: 's'}
count_updated = dict(filter(lambda val: val[0] % 3 == 0,
count.items()))
is iterating Dictionary with Lambda function?
It will produce:
{8: 'u', 4: 't', 9: 'z', 10: 'j', 5: 'k', 3: 's'}
{9: 'z', 3: 's'}
from Python dictionary filter + Examples.
I have a dictionary like the following. Key value pairs or username:name
d = {"user2":"Tom Cruise", "user1": "Tom Cruise"}
My problem is that i need to sort these by the Name, but if multiple users contain the same name like above, i then need to sort those by their username. I looked up the sorted function but i dont really understand the cmp parameter and the lambda. If someone could explain those and help me with this that would be great! Thanks :)
cmp is obsolescent. lambda just makes a function.
sorted(d.iteritems(), key=operator.itemgetter(1, 0))
I'm just going to elaborate on Ignacio Vazquez-Abrams's answer. cmp is deprecated. Don't use it. Use the key attribute instead.
lambda makes a function. It's an expression and so can go places that a normal def statement can't but it's body is limited to a single expression.
my_func = lambda x: x + 1
This defines a function that takes a single argument, x and returns x + 1. lambda x, y=1: x + y defines a function that takes an x argument, an optional y argument with a default value of 1 and returns x + y. As you can see, it's really just like a def statement except that it's an expression and limited to a single expression for the body.
The purpose of the key attribute is that sorted will call it for each element of the sequence to be sorted and use the value that it returns for comparison.
list_ = ['a', 'b', 'c']
sorted(list_, key=lambda x: 1)
Just read the rest for a hypothetical example. I didn't look at problem closely enough before writing this. It will still be educational though so I'll leave it up.
We can't really say much more because
You can't sort dicts. Do you have a list of dictss? We could sort that.
You haven't shown a username key.
I'll assume that it's something like
users = [{'name': 'Tom Cruise', 'username': user234234234, 'reputation': 1},
{'name': 'Aaron Sterling', 'username': 'aaronasterling', 'reputation': 11725}]
If you wanted to confirm that I'm more awesome than Tom Cruise, you could do:
sorted(users, key=lambda x: x['reputation'])
This just passes a function that returns the 'reputation' value for each dictionary in the list. But lambdas can be slower. Most of the time operator.itemgetter is what you want.
operator.itemgetter takes a series of keys and returns a function that takes an object and returns a tuple of the value of its argument.
so f = operator.itemgetter('name', 'username') will return essentially the same function as
lambda d: (d['name'], d['username']) The difference is that it should, in principle run much faster and you don't have to look at ugly lambda expressions.
So to sort a list of dicts by name and then username, just do
sorted(list_of_dicts, operator.itemgetter('name', 'username'))
which is exactly what Ignacio Vazquez-Abrams suggested.
You should know that dict can't be sorted. But python 2.7 & 3.1 have this class collections.OrderedDict.
So,
>>> from collections import OrderedDict
>>> d=OrderedDict({'D':'X','B':'Z','C':'X','A':'Y'})
>>> d
OrderedDict([('A', 'Y'), ('C', 'X'), ('B', 'Z'), ('D', 'X')])
>>> OrderedDict(sorted((d.items()), key=lambda t:(t[1],t[0])))
OrderedDict([('C', 'X'), ('D', 'X'), ('A', 'Y'), ('B', 'Z')])
What is this called in python:
[('/', MainPage)]
Is that an array .. of ... erhm one dictionary?
Is that
()
A tuple? ( or whatever they call it? )
Its a list with a single tuple.
Since no one has answered this bit yet:
A tuple? ( or whatever they call it? )
The word "tuple" comes from maths. In maths, we might talk about (ordered) pairs, if we're doing 2d geometry. Moving to three dimensions means we need triples. In higher dimensions, we need quadruples, quintuples, and, uh, whatever the prefix is for six, and so on. This starts to get to be a pain, and mathematicians also love generalising ("let's work in n dimensions today!"), so they started using the term "n-tuple" for an ordered list of n things (usually numbers).
After that, a bit of natural laziness is all you need to drop the "n-" and we end up with tuples.
Note that this:
("is not a tuple")
A tuple is defined by the commas, except in the case of the zero-length tuple. This:
"is a tuple",
because of the comma at the end. The parentheses just enforce grouping (again, except in the case of a zero-length tuple.
That's a list of tuples.
This is a list of integers: [1, 2, 3, 4, 5]
This is also a list of integers: [1]
This is a (string, integer) tuple: ("hello world", 42)
This is a list of (string, integer) tuples: [("a", 1), ("b", 2), ("c", 3)]
And so is this: [("a", 1)]
In Python, there's not much difference between lists and tuples. However, they are conceptually different. An easy way to think of it is that a list contains lots of items of the same type (homogeneous) , and a tuple contains a fixed number of items of different types (heterogeneous). An easy way to remember this is that lists can be appended to, and tuples cannot, because appending to a list makes sense and appending to a tuple doesn't.
Python doesn't enforce these distinctions -- in Python, you can append to a tuple with +, or store heterogeneous types in a list.
Yes, it's a tuple.
They look like this:
()
(foo,)
(foo, bar)
(foo, bar, baz)
etc.
[('/', MainPage)]
That's a list consisting of a two element tuple.
()
That's a zero element tuple.
It is a list of tuple(s). You can verify that by
x=[('/', MainPage)]
print type(x) # You will find a <list> type here
print type(x[0]) # You will find a <tuple> type here
You can build a dictionary from this type of structure (may be more tuple inside the list) with this code
my_dict = dict(x) # x=[('/',MainPage)]
It is a list of tuples containing one tuple.
A tuple is just like a list except that it is immutable, meaning that it can't be changed once it's created. You can't add, remove, or change elements in a tuple. If you want your tuple to be different, you have to create a new tuple with the new data. This may sound like a pain but in reality tuples have many benefits both in code safety and speed.
It's a list of just one tuple. That tuple has two elements, a string and the object MainPage whatever it is.
Both lists and tuples are ordered groups of object, it doesn't matter what kind of object, they can be heterogeneous in both cases.
The main difference between lists and tuples is that tuples are immutable, just like strings.
For example we can define a list and a tuple:
>>> L = ['a', 1, 5, 'b']
>>> T = ('a', 1, 5, 'b')
we can modify elements of L simply by assigning them a new value
>>> print L
['a', 1, 5, 'b']
>>> L[1] = 'c'
>>> print L
['a', 'c', 5, 'b']
This is not true for tuples
>>> print T
('a', 1, 5, 'b')
>>> T[1] = 'c'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
This is because they are immutable.
Tuples' elements may be mutable, and you can modify them, for example:
>>> T = (3, ['a', 1, 2], 'lol')
>>> T[1]
['a', 1, 2]
>>> T[1][0] = 'b'
>>> T
(3, ['b', 1, 2], 'lol')
but the list we edited is still the same object, we didn't replaced the tuple's element.