python 2.7 unique calculation issue - python

Using Python 2.7, I have a list, and each element in the list is a (sub-list) -- a list of tuples. I want to remove the duplicate sub-list, I post input and expected output. I tried to use set, but there is error said list is not hashable. Anyone have good elegant code solutions? Thanks.
a=[[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
# expect output
'''
a=[[(1,2),(1,3)],
[(1,3),(1,2)]]
'''

Try this! This is the simplest method.
a = [[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
print [list(i) for i in set(map(tuple, a))]
[[(1, 3), (1, 2)], [(1, 2), (1, 3)]] //output
The above one is without any library support and also the ordering of the original list can't be ensured.
If you want to preserve the order of the list, then go for collections library.
from collections import OrderedDict
a = [[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
print map(list, OrderedDict.fromkeys(map(tuple, a)))
[[(1, 2), (1, 3)], [(1, 3), (1, 2)]] //output

I think you can use a set, something like below
a=[[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
unique_list = [list(x) for x in set(tuple(x) for x in a)]
print unique_list
Output:
[[(1, 3), (1, 2)], [(1, 2), (1, 3)]]
See working repl here - https://repl.it/EinE/1

Related

Python print statement prints address instead of value

This is the code which I have did
from itertools import product
lst1=list(map(int,input().split()))
lst2=list(map(int,input().split()))
l3=product(lst1,lst2)
Input:
1 2
2 3
Output:
<itertools.product object at 0x7f02bdedb500>
Output that I want:
(1, 3) (1, 4) (2, 3) (2, 4)
I have tried adding parentheses, brackets and also tried to store the value in a variable and printed it. I still couldn't able to get that output. I don't want the output as a list, the expected output is shown above.
product(lst1,lst2) returns a itertools.product object just use map function to update internal tuple 1st index item or iterate though each element.
So use map function and update each tuple by 1 using lambda function :
l3= list(map(lambda i: (i[0], i[-1]+1), product(lst1,lst2)))
print(l3)
OUTPUT :
[(1, 3), (1, 4), (2, 3), (2, 4)]
Problem with this output is that it is string representation of list object so the best way is to go with this method.
So use iterate though this iterable object :
for i in l3:
i = list(i)
i[-1] += 1
print(tuple(i), end=' ')
OUTPUT :
(1, 3) (1, 4) (2, 3) (2, 4)
Convert or cast it to list, it works.
from itertools import product
lst1=list(map(int,input().split()))
lst2=list(map(int,input().split()))
l3=list(product(lst1,lst2))
"itertools.product" returns a generator, to get the list output you need :
list(l3)
However, not sure where you got your values from, I got :
[(1, 2), (1, 3), (2, 2), (2, 3)]
You can iterate l3 to get the desired output:
for i in l3:
print(i, end=" ")

Problem in getting unique elements from list of tuples

I got sample input as a=[(1,2),(2,3),(1,1),(2,1)], and the expected ouput is a=[(1,2),(2,3),(1,1)].
Here, (2,1) is removed, since the same combinational pair (1,2) is already available. I tried below code to remove duplicate pairs
map(tuple, set(frozenset(x) for x in a))
However, the output is [(1, 2), (2, 3), (1,)]. How to get (1,1) pair as (1,1) instead of (1,).
You can use a dict instead of a set to map the frozensets to the original tuple values. Build the dict in reversed order of the list so that duplicating tuples closer to the front can take precedence:
{frozenset(x): x for x in reversed(a)}.values()
This returns:
[(1, 2), (2, 3), (1, 1)]
This is one approach using sorted
Ex:
a=[(1,2),(2,3),(1,1),(2,1)]
print set([tuple(sorted(i)) for i in a])
Output:
set([(1, 2), (2, 3), (1, 1)])

How do I return a list of tuples with each unique string and its count given a list of strings?

Not sure where to start...
item() gives a dictionary and I don't want that.
I would say I need to loop through the list....
Please someone give me some hints so I can get started!
EDIT:
count_of_names(names)
counts_of_names(['John', John', 'Catherine', 'John', 'Christopher', 'Catherine']'
output:
[('Catherine', 2), ('Christopher', 1), ('John', 3)]
This is a hard way to do it:
x = [1,3,2,5,6,6,3,2]
x_tuple = []
y = set(x)
for i in y:
x_tuple.append((i,x.count(i)))
print(x_tuple)
You may use collections.Counter() to achieve this. Example:
>>> x = [1,2,3,4,1,1,2,3]
>>> my_list = Counter(x).items()
>>> my_list
[(1, 3), (2, 2), (3, 2), (4, 1)]
# In order to sort the list base based on value of tuple at index `1` and then index `0`
>>> sorted(my_list, key=lambda x: (x[1], x[0]))
[(4, 1), (2, 2), (3, 2), (1, 3)]
Use set and list comprehension:
def counts_of_names(names):
return [(name, names.count(name)) for name in set(names)]

Double sort with reverse

It is easy to implement a regular double sort:
pairs = [(1, 2), (2, 1), (1, 3), (2, 4), (3, 1)]
sorted(pairs,key=lambda x: (x[0],x[1]))
# out: [(1, 2), (1, 3), (2, 1), (2, 4), (3, 1)]
I am interested how to do it with the second elements in the reverse order. This can be easily implemented by grouping the pairs by the first item at first and then adding the the sorted second items together. I have implemented this both using itertools.groupby and defaultdict. Still, it remains far more complex, than the regular double sort, so i wonder, if there is a neat trick to do it in a more concise way.
double_sort(pairs)
# out: [(1, 3), (1, 2), (2, 4), (2, 1), (3, 1)]
PS! I know how to do it with numpy.argsort and would mostly like to see a standard lib approach.
This will work for numbers and similar data types
sorted(pairs, key=lambda x: (x[0], -x[1]))
This will work for all comparable types only in Python 2 :(
sorted(pairs, lambda x, y: cmp(x[0], y[0]) or cmp(y[1], x[1]))

Making list of list oneliner -python

I have a list
l=[(1,2),(1,6),(3,4),(3,6),(1,4),(4,3)]
I want to return a list that contains lists by the first number in each tuple.
Something like this:
[[2,4,6],[4,6],[3]]
To make a program that iterates on list and writing a whole function that does it is easy.
I want to find a oneliner - python way of doing it.
Any ideas?
>>> from itertools import groupby
>>> from operator import itemgetter
>>> L = [(1,2), (1,6), (3,4), (3,6), (1,4), (4,3)]
>>> [[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
[[2, 4, 6], [4, 6], [3]]
Explanation
This works by using itertools.groupby. groupby finds consecutive groups in an iterable, returning an iterator through key, group pairs.
The argument given to groupby is a key function, itemgetter(0) which is called for each tuple, returning the first item as the key to groupby.
groupby groups elements in their original order so if you want to group by the first number in the list, it must first be sorted so groupby can go through the first numbers in ascending order and actually group them.
>>> sorted(L)
[(1, 2), (1, 4), (1, 6), (3, 4), (3, 6), (4, 3)]
There is the sorted list where you can clearly see the groups that will be created if you look back to the final output. Now you can use groupby to show the key, group pairs.
[(1, <itertools._grouper object at 0x02BB7ED0>), (3, <itertools._grouper object at 0x02BB7CF0>), (4, <itertools._grouper object at 0x02BB7E30>)]
Here are the sorted items grouped by the first number. groupby returns the group for each key as an iterator, this is great and very efficient but for this example we will just convert it to a list to make sure it's working properly.
>>> [(k, list(v)) for k,v in groupby(sorted(L), itemgetter(0))]
[(1, [(1, 2), (1, 4), (1, 6)]), (3, [(3, 4), (3, 6)]), (4, [(4, 3)])]
That is almost the right thing but the required output shows only the 2nd number in the groups in each list. So the following achieves the desired result.
[[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
l = [(1, 2), (1, 6), (3, 4), (3, 6), (1, 4), (4, 3)]
d = {}
for (k, v) in l:
d.setdefault(k, []).append(v)
print d.values()
I know it's not a one liner, but perhaps it's easier to read than a one liner.

Categories