Reputation: 1295
I have a list of arrays that contains a dictionary in python. Here there is my example:
[[(0, 1), 'up'], [(1, 2), 'right'], [(3, 2), None], [(0, 0), 'up'], [(3, 0), 'left'], [(3, 1), None], [(2, 1), 'up'], [(2, 0), 'left'], [(2, 2), 'right'], [(1, 0), 'left'], [(0, 2), 'right']]
What I need to do is to order it base on the key (x, y) first on x and after on y: is it possible?
Here there is what I want as output:
[[(0, 0), 'up'], [(0, 1), 'up'], [(0, 2), 'right'], [(1, 0), 'left'],[(1, 2), 'right'], [(2, 0), 'left'], ....]
I have tried using that code:
s = sorted(s, key = lambda x: (x[0][0][0], x[0][0][1]))
But it returns:
TypeError: 'int' object has no attribute '__getitem__'
Upvotes: 2
Views: 484
Reputation: 140186
You're going too deep in the subscripting. In your case just sort on the tuple, the lexicographical order of the tuple suits your problem:
sorted(s,key = lambda x : x[0])
or without lambda
with operator.itemgetter
:
sorted(s,key = operator.itemgetter(0))
result:
[[(0, 0), 'up'], [(0, 1), 'up'], [(0, 2), 'right'], [(1, 0), 'left'], [(1, 2), 'right'], [(2, 0), 'left'], [(2, 1), 'up'], [(2, 2), 'right'], [(3, 0), 'left'], [(3, 1), None], [(3, 2), None]]
The interesting thing about this dataset is that you cannot use sorted(s)
without a key because of your last argument, which can be a string or None
.
On those particular values, it seems to work, but in the case of a tie (2 identical tuples, and the other terms being a string and None
), sort
would have compare the string and None
, and that doesn't work in Python 3.
But could be solved by using a key function like lambda x : (x[0],x[1] or "")
so if x[1]
is None
it changes it into an empty string and the comparison works (if None
should be first, else use lambda x : (x[0],-(x[1] is not None),x[1] or ""
to put None
after any string).
Upvotes: 3