Remove duplicated tuples with included lists from list - python

i have a list with tuples:
managed_list = [ ('a', [1,2]), ('a', [1,2]), ('b', [2,2]), ('b', [2,2])]
need to get:
managed_list = [ ('a', [1,2]), ('b', [2,2]) ]
tried:
seen = set()
[[n for n in x if n not in seen and not seen.add(n)] for x in managed_list]
getting:
TypeError: unhashable type: 'list'

Right, you can't use a list or a structure containing a list (or another unhashable type) in a set. Without changing your input structure, you could use itertools.groupby and then just discard the iterator through the duplicates:
import itertools
uniques = [x[0] for x in itertools.groupby(sorted(managed_list))]
Incidentally if it were not for the unhashable key issue (e.g. if the lists were tuples instead), your expression could be simplified to:
list(set(managed_list))
You do not need the extra code in the list comprehension for this.

You can also use collections.OrderedDict to remove duplicate keys.
>>> from collections import OrderedDict
>>> OrderedDict([ ('a', [1,2]), ('a', [1,2]), ('b', [2,2]), ('b', [2,2])]).items()
[ ('a', [1,2]), ('b', [2,2]) ]
Keep in mind that in case of duplicate keys, the right-most entry will be the one included in the output.

Related

Why tuples in a set won't convert to any other type in a loop?

I'm trying to remove a certain item from a set of tuples. to do so I must convert the tuples to a list or a set (i.e. a mutable object). I'm trying to do in a for loop but the tuples won't convert and my item is yet to be removed.
a = [('A', 'C'), ('B', 'C'), ('B', 'C')]
for i in a:
i = list(i)
if 'C' in i:
i.remove('C')
print(a)
This is the output:
[('A', 'C'), ('B', 'C'), ('B', 'C')]
You got the right intuition. As your tuples are immutable, you need to create new ones.
However, in your code, you create lists, modify them, but fail to save them back in the original list.
You could use a list comprehension.
[tuple(e for e in t if e != 'C') for t in a]
Output:
[('A',), ('B',), ('B',)]
You are modifying the list but are not creating a new list.
Try this:
a = [('A', 'C'), ('B', 'C'), ('B', 'C')]
b = []
for i in a:
i = list(i)
if 'C' in i:
i.remove('C')
b.append(i)
print(b)

how to pair each 2 elements of a list?

I have a list like this
attach=['a','b','c','d','e','f','g','k']
I wanna pair each two elements that followed by each other:
lis2 = [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'k')]
I did the following:
Category=[]
for i in range(len(attach)):
if i+1< len(attach):
Category.append(f'{attach[i]},{attach[i+1]}')
but then I have to remove half of rows because it also give 'b' ,'c' and so on. I thought maybe there is a better way
You can use zip() to achieve this as:
my_list = ['a','b','c','d','e','f','g','k']
new_list = list(zip(my_list[::2], my_list[1::2]))
where new_list will hold:
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'k')]
This will work to get only the pairs, i.e. if number of the elements in the list are odd, you'll loose the last element which is not as part of any pair.
If you want to preserve the last odd element from list as single element tuple in the final list, then you can use itertools.zip_longest() (in Python 3.x, or itertools.izip_longest() in Python 2.x) with list comprehension as:
from itertools import zip_longest # In Python 3.x
# from itertools import izip_longest ## In Python 2.x
my_list = ['a','b','c','d','e','f','g','h', 'k']
new_list = [(i, j) if j is not None else (i,) for i, j in zip_longest(my_list[::2], my_list[1::2])]
where new_list will hold:
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h'), ('k',)]
# last odd number as single element in the tuple ^
You have to increment iterator i.e by i by 2 when moving forward
Category=[]
for i in range(0, len(attach), 2):
Category.append(f'{attach[i]},{attach[i+1]}')
Also, you don't need the if condition, if the len(list) is always even
lis2 = [(lis[i],lis[i+1]) for i in range(0,len(lis),2)]
lis2
You can use list comprehension

How to explode a list of tuples consisting of a string and a list with n values?

I have a list of tuples.
l= [([a,b,c],'R1'),
([d],'R2'),
([e,f],'R3)]
Which I want to explode to
l = [(a,'R1'),
(b,'R1'),
(c,'R1'),
(d,'R2'),
(e,'R3'),
(f,'R3')]
How would I do this?
You can use a list comprehension to iterate over the tuples, and over the lists in the inner loop to obtain the corresponding tuples:
[(k,j) for i,j in l for k in i]
# [('a', 'R1'), ('b', 'R1'), ('c', 'R1'), ('d', 'R2'), ('e', 'R3'), ('f', 'R3')]

"Transpose" (rotate?) nested list

I have a list of lists of lists like this:
[
[
[a,b],
[c,d]
],
[
[e,f],
[g,h]
]
]
Basically, this is a cube of values.
What I want is a different order of items in the same cube, like this:
[
[
[a,e],
[b,f]
],
[
[c,g],
[d,h]
]
]
And, preferably, in a one-liner (yes, I do know that's not the best practice).
I know of the map(list, *zip(a)) trick, but i couldn't figure out how to apply it here. Something with lambdas and maps, probably?
UPD: As for what I need it for --- I've done some tests for speeds of different sorting algorithms; each deepest list has values -- the times that the sorting algorithms that I tested took. These lists are in lists, which represent different types of tests, and the outer list has the same thing repeated for different test sizes. After such rotation, I will have list (test size) of lists (test type) of lists (sort type) of items (time), which is so much more convenient to plot.
If I understand you correctly, you want to first transpose all the sublists then transpose the newly transposed groups:
print([list(zip(*sub)) for sub in zip(*l)])
Output:
In [69]: [list(zip(*sub)) for sub in zip(*l)]
Out[69]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h')]]
If you want some map foo with a lambda:
In [70]: list(map(list, map(lambda x: zip(*x), zip(*l))))
Out[70]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h'
For python2 you don't need the extra map call but I would use itertools.izip to do the initial transpose.:
In [9]: from itertools import izip
In [10]: map(lambda x: zip(*x), izip(*l))
Out[10]: [[('a', 'e'), ('b', 'f')], [('c', 'g'), ('d', 'h')]]

Python: Munging data with '.join' (TypeError: sequence item 0: expected string, tuple found)

I have data in following format:
[('A', 'B', 'C'),
('B', 'C', 'A'),
('C', 'B', 'B')]
I'm looking to get this:
ABC
BCA
CBB
I'm able to convert one tuple at the time:
>> "".join(data[0])
.. 'ABC'
However when I'm trying to conver the whole list Python gives me an error:
>> "".join(data[:])
.. TypeError: sequence item 0: expected string, tuple found
Any advice how I'll be able to convert the whole list?
Thank you!
.join expects a sequence of strings, but you're giving it a sequence of tuples.
To get the result you posted, you'll need to join each element in each tuple, and then join each tuple together:
print('\n'.join(''.join(elems) for elems in data))
This works because .join will accept a generator expression, allowing you to iterate over data (your list of tuples).
We therefore have two joins going on: the inner join builds a string of the three letters (eg, 'ABC'), and the outer join places newline characters ('\n') between them.
lst=[('A', 'B', 'C'),
('B', 'C', 'A'),
('C', 'B', 'B')]
for x in lst:
print ("".join(x))
Output is;
>>>
ABC
BCA
CBB
>>>
One-liner;
print ("\n".join(["".join(x) for x in lst]))
You have to reach each element in the list first.
a = [('A', 'B', 'C'), ('B', 'C', 'A'), ('C', 'B', 'B')]
print ["".join(line) for line in a]

Categories