Sorted sublist in list - python

assume i have
a=[[0,1],[2,1],[0,2],[1,3]]
i would like to have a result like this
b=[[0,1],[0,2],[1,2],[1,3]]
The tricky part is to sort the [2,1] to [1,2] and sort the whole list again. I tried
sorted(a, key=lambda x: (x[0]))
but it give me [[0,1],[0,2],[1,3],[2,1]]
Any suggestion?

Try to sort the sublist first:
print sorted([sorted(i) for i in a])
Update It could be done slightly better, passing a list comprehension to sorted() results in a copy of the list being made, so you can just remove it:
print sorted(sorted(i) for i in a)
Result
[[0, 1], [0, 2], [1, 2], [1, 3]]
As #PM2Ring said, using the lambda maybe return the wrong result, it should be removed.

Can you try the below using comprehension.
>>> b=sorted([sorted(s) for s in a])
>>> b
[[0, 1], [0, 2], [1, 2], [1, 3]]
It should work.

try this:
b=sorted([sorted(small_list) for small_list in a ])

Try this:
>>> [sorted(i) for i in sorted(a, key=lambda x: (min(x), sum(x)))]
[[0, 1], [0, 2], [1, 2], [1, 3]]

Related

Compare 1st element of list from nest list in python

I have a list of lists like following :
[[a1,a2], [b1,b2],...., [n1]]
and I want to find whether the first elements of all these lists are equal?
I'd prefer to do this with a list comprehension unless there's a reason to avoid it, for readability's sake.
list_of_lists = [[1, 2], [1, 3], [1, 4]]
len(set([sublist[0] for sublist in list_of_lists])) == 1
# True
The solution is quite straight forward.
Transpose your list. Use zip to perform this task
Index the first row of your transposed list
Use set to remove duplicate
Determine if no of elements is equal to 1
>>> test = [[1, 2], [1, 3], [1, 4]]
>>> len(set(zip(*test)[0])) == 1
True
Note
If you are using Py 3.X, instead of slicing, wrap the call to zip with next
>>> len(set(next(zip(*test)))) == 1
How about?
>>> from operator import itemgetter
>>> test = [[1, 2], [1, 3], [1, 4]]
>>> len(set(map(itemgetter(0), test))) == 1
True
>>> test.append([2, 5])
>>> test
[[1, 2], [1, 3], [1, 4], [2, 5]]
>>> len(set(map(itemgetter(0), test))) == 1
False
And another way would be (Thanks, Peter DeGlopper!)
all(sublist[0] == test[0][0] for sublist in test)
This version would short-circuit too, so it wouldn't need to check every element in every case.
You can create a list of first elements compared to the first sublist's first element:
False not in [len(yourList[0])>0 and len(x)>0 and x[0] == yourList[0][0] for x in yourList]
With a one liner:
>>> sample = [[1, 2], [1, 3], [1, 4]]
>>> reduce(lambda x, y: x if x == y[0] else None, sample, sample[0][0])
1
>>> sample = [[0, 2], [1, 3], [1, 4]]
>>> reduce(lambda x, y: x if x == y[0] else None, sample, sample[0][0])
None
Try this...
>>> test = [[1, 2], [1, 3], [1, 4]]
>>> eval("==".join(map(lambda x: str(x[0]), test)))
True

Removing commutative pairs in a list in Python

I got a list as follows:
list_1 = [[3, 0], [0, 3], [3, 4]]
I'm trying to filter out the commutative elements in this. For example, [3,0] and [0,3] are the same and I need to keep only one of them. I tried converting this into a set, and it didn't help. I also tried iterating, but it's causing real overhead. Is there any Pythonic way to do this?
Thanks.
For example, you can use dict comprehension:
>>> {tuple(sorted(t)): t for t in list_1}.values()
[[0, 3], [3, 4]]
You can use a set of frozensets for the filtering.
If order does not matter:
>>> map(list, set(frozenset(t) for t in list_1))
[[3, 4], [0, 3]]
To retain order:
list_1 = [[3, 0], [0, 3], [3, 4]]
seen = set()
filtered = []
for item in list_1:
item_set = frozenset(item)
if item_set not in seen:
filtered.append(item)
seen.add(item_set)
Result:
>>> filtered
[[3, 0], [3, 4]]

Python how to sort a list with list elements

How can i sort a list in python?
I have this list:
list=[[[1,2,3],0],[[13,2,3],2],[[2,0,0],13]]
And i want to sort by second element from first list.
I've think that should be something like this .
list.sort(key=lambda x:x[0[1]])
And I don't know the correct syntax.
Your indexing is wrong. You want to index the list, not the integer.
list.sort(key=lambda x: x[0][1])
Well, its simple enough:
>>> l=[[[1,2,3],0],[[13,2,3],2],[[2,0,0],13]]
>>> sorted(l, key=lambda x: x[0][1])
[[[2, 0, 0], 13], [[1, 2, 3], 0], [[13, 2, 3], 2]]

Processing a list of lists

I have a list of lists, say:
arr = [[1, 2], [1, 3], [1, 4]]
I would like to append 100 to each of the inner lists. Output for the above example would be:
arr = [[1, 2, 100], [1, 3, 100], [1, 4, 100]]
I can of course do:
for elem in arr:
elem.append(100)
But is there something more pythonic that can be done? Why does the following not work:
arr = [elem.append(100) for elem in arr]
The second version should be written like arr = [elem + [100] for elem in arr]. But the most pythonic way if you ask me is the first one. The for construct has it's own use, and it suits very well here.
Note that your code also works - the only thing you have to know is that there is no need to assign result to variable in such a case:
arr = [[1, 2], [1, 3], [1, 4]]
[x.append(100) for x in arr]
After execution arr will contain updated list [[1, 2, 100], [1, 3, 100], [1, 4, 100]], e.g it work like in-place update, but this not very common practice to do this.
The same result you will get in the next case:
map(lambda x: x.append(100), arr)
As was discussed you can use list comprehension or map to do this with assigning result to any variable:
res = map(lambda x: x + [100], arr)
You can do
[a + [100] for a in arr]
The reason why your append doesn't work is that append doesn't return the list, but rather None.
Of course, this is more resource intensive than just doing append - you end up making copies of everything.
This is the more pythonic way
for elem in arr:
elem.append(100)
but as an option you can also try this:
[arr[i].append(100) for i in range(len(arr))]
print arr # It will return [[1, 2, 100], [1, 3, 100], [1, 4, 100]]

Python, working with list comprehensions

I have such code:
a = [[1, 1], [2, 1], [3, 0]]
I want to get two lists, the first contains elements of 'a', where a[][1] = 1, and the second - elements where a[][1] = 0. So
first_list = [[1, 1], [2, 1]]
second_list = [[3, 0]].
I can do such thing with two list comprehension:
first_list = [i for i in a if i[1] == 1]
second_list = [i for i in a if i[1] == 0]
But maybe exists other (more pythonic, or shorter) way to do this? Thanks for your answers.
List comprehension are very pythonic and the recommended way of doing this. Your code is fine.
If you want to have it in a single line you could do something like
first_list, second_list = [i for i in a if i[1] == 1], [i for i in a if i[1] == 0]
Remember that, "Explicit is better than implicit."
Your code is fine
You can use sorted() and itertools.groupby() to do this, but I don't know that it would qualify as Pythonic per se:
>>> dict((k, list(v)) for (k, v) in itertools.groupby(sorted(a, key=operator.itemgetter(1)), operator.itemgetter(1)))
{0: [[3, 0]], 1: [[1, 1], [2, 1]]}
what about this,
In [1]: a = [[1, 1], [2, 1], [3, 0]]
In [2]: first_list = []
In [3]: second_list = []
In [4]: [first_list.append(i) if i[1] == 1 else second_list.append(i) for i in a]
Out[4]: [None, None, None]
In [5]: first_list, second_list
Out[5]: ([[1, 1], [2, 1]], [[3, 0]])
instead of two sublist, I prefer dict (or defaultdict, OrderedDict, Counter, etc.)
In [6]: from collections import defaultdict
In [7]: d = defaultdict(list)
In [8]: [d[i[1]].append(i) for i in a]
Out[8]: [None, None, None]
In [9]: d
Out[9]: {0: [[3, 0]], 1: [[1, 1], [2, 1]]}
If the lists are reasonably short then two list comprehensions will do fine: you shouldn't be worried about performance until your code is all working and you know it is too slow.
If your lists are long or the code runs often and you have demonstrated that it is a bottleneck then all you have to do is switch from list comprehensions to a for loop:
first_list, second_list = [], []
for element in a:
if element[1] == 1:
first_list.append(element)
else:
second_list.append(element)
which is both clear and easily extended to more cases.
list comprehensions are great. If you want slightly more simple code (but slightly longer) then just use a for loop.
Yet another option would be filters and maps:
a = [[1, 1], [2, 1], [3, 0]]
g1=filter(lambda i: i[1]==1,a)
g1=map(lambda i: i[0],g1)
g2=filter(lambda i: i[1]==0,a)
g2=map(lambda i: i[0],g2)
print g1
print g2

Categories

Resources