check duplicates in unhashable list of lists [duplicate] - python

This question already has answers here:
Checking if a list has duplicate lists
(7 answers)
Closed 3 years ago.
I have the following list:
L = [['a', 'b'], ['x'], ['a', 'b', 'c'], ['a', 'b']]
I want to check whether there are duplicates in the list.
Have tried:
def checkIfDuplicates_(listOfElems):
''' Check if given list contains any duplicates '''
for elem in listOfElems:
if listOfElems.count(elem) > 1:
return True
return False
and
len(L)==len(set(L))
and turn each sublist into tuples
check_L = list(set(tuple(L) for x in L))
Not working

You were actually really close with this:
check_L = list(set(tuple(L) for x in L))
There is a minor mistake, in that you are using tuple(L) where you actually want tuple(x). If we correct that, we get:
>>> list(set(tuple(x) for x in L))
[('a', 'b', 'c'), ('x',), ('a', 'b')]
And to turn back into a nested list, we can do this:
>>> [list(y) for y in set(tuple(x) for x in L)]
[['a', 'b', 'c'], ['x'], ['a', 'b']]
Hope that helps!

Related

Flatten a list with sublists and strings [duplicate]

This question already has answers here:
Flatten an irregular (arbitrarily nested) list of lists
(51 answers)
How do I make a flat list out of a list of lists?
(34 answers)
Closed 1 year ago.
How can I flatten a list of lists into a list?
For ex,:
Input_List = [['a', 'b'],'c','d',['e', 'f']]
Expectation:
Final_List = ['a','b','c','d','e','f']
You will need to check the type of each list item to determine if it is merely a value to output or a sublist to expand.
Using a list comprehension:
Input_List = [['a', 'b'],'c','d',['e', 'f']]
Final_List = [v for i in Input_List for v in (i if isinstance(i,list) else [i])]
print(Final_List)
['a', 'b', 'c', 'd', 'e', 'f']
Or using an iterative loop:
Final_List = []
for item in Input_List:
if isinstance(item,list): Final_List.extend(item)
else: Final_List.append(item)
print(Final_List)
['a', 'b', 'c', 'd', 'e', 'f']
Or using a recursive function if you need to flatten all levels of nested lists:
def flat(A):
return [v for i in A for v in flat(i)] if isinstance(A,list) else [A]
Input_List = [['a', 'b'],'c','d',['e2', 'f3',['x','y']]]
Final_List = flat(Input_List)
print(Final_List)
['a', 'b', 'c', 'd', 'e2', 'f3', 'x', 'y']
this working only for -> multdimensional at the same dimension
from itertools import chain
ini_list = [[1, 2, 3],
[3, 6, 7],
[7, 5, 4]]
print ("initial list ", str(ini_list))
flatten_list = list(chain.from_iterable(ini_list))
print ("final_result", str(flatten_list))
If some arrays isn't nested - then
def flatten(something):
if isinstance(something, (list, tuple, set, range)):
for sub in something:
yield from flatten(sub)
else:
yield something
test = flatten(ini_list)
list(test)

How to insert elements in a nested List in Python? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 4 years ago.
I do not have much experience in Python.
All I want to do is to insert elements in nested lists.I have two lists which seems to be similar but their behaviour is completely different.
list1 = [['a','b']] * 3
list2 = [['a','b'],['a','b'],['a','b']]
When I output print these two lists both give same output:
[['a', 'b'], ['a', 'b'], ['a', 'b']]
But when I try to insert elements in nested lists both do that in a different way. Below is the code for inserting elements in nested list.
list1 = [['a','b']] * 3
for item in list1:
item.append("Hello")
print (list1)
This outputs
[['a', 'b', 'Hello', 'Hello', 'Hello'], ['a', 'b', 'Hello', 'Hello', 'Hello'], ['a', 'b', 'Hello', 'Hello', 'Hello']]
While when I define list in the following way it does exactly what I want.
list2 = [['a','b'],['a','b'],['a','b']]
for item in list2:
item.append("Hello")
print (list2)
This gives following output:
[['a', 'b', 'Hello'], ['a', 'b', 'Hello'], ['a', 'b', 'Hello']].
Why are these two behaving differently?
list1 = [['a','b']] * 3
list2 = [['a','b'],['a','b'],['a','b']]
Screenshot of Program output
list1 = [['a', 'b']] * 3
This creates a list of lists, as you know. However, the nested lists are actually all references to the same list object.
So when you iterate over list1 with
for item in list1:
item refers to the same list object on each iteration. So you repeated append to the same list.
On the other hand, list2 in your example code is explicitly assigned a list with three different lists. Those lists happen to have the same elements, but they are distinct lists.
When you use the * operator here, you are saying "I want 3 of these".
So you're getting 3 references to the same ['a', 'b']. In your case, you're adding 'Hello' to that same ['a', 'b'] reference.
List of lists changes reflected across sublists unexpectedly
If you want to make 3 separate references, try using list comprehension:
>>> x = [['a', 'b'] for i in range(0, 3)]
>>> x
[['a', 'b'], ['a', 'b'], ['a', 'b']]
>>> x[0].append('Hello')
>>> x
[['a', 'b', 'Hello'], ['a', 'b'], ['a', 'b']]

I'd like to make the python's list to ['a','a','b',b','c','c'] from ['a','b','c'] [duplicate]

This question already has answers here:
Duplicate each member in a list [duplicate]
(12 answers)
Closed 5 years ago.
I'd like to make the python's list to ['a','a','b',b','c','c'] from ['a','b','c'].
Anyboday know to do this?
Thank you !
For something that more or less says “I want to repeat each element twice”, there’s the nested list comprehension with range:
>>> l = ['a', 'b', 'c']
>>> [x for x in l for _ in range(2)]
['a', 'a', 'b', 'b', 'c', 'c']
You can make it a tiny bit shorter with a list multiplication if you find that more readable and won’t need to extend 2 to a large number and convert the list comprehension to a generator expression:
>>> l = ['a', 'b', 'c']
>>> [y for x in l for y in [x, x]]
If you’re a fan of Haskell, where l >>= replicate 2 would work, you can imitate that:
import itertools
from functools import partial
from operator import mul
def flat_map(iterable, f):
return itertools.chain.from_iterable(map(f, iterable))
l = ['a', 'b', 'c']
flat_map(l, partial(mul, 2))
You could always create a new list:
for x in oldList:
newList.append(x)
newList.append(x)
Note that this will create a new list rather than modifying the old one!
source = ['a','b','c']
result = [el for el in source for _ in (1, 2)]
print(result)
gives you
['a', 'a', 'b', 'b', 'c', 'c']

Would like to prevent dupes in a python list of lists

I am creating a list of lists and want to prevent dupes. For example, I have:
mainlist = [[a,b],[c,d],[a,d]]
the next item (list) to be added is [b,a] which is considered a duplicate of [a,b].
UPDATE
mainlist = [[a,b],[c,d],[a,d]]
swap = [b,a]
for item in mainlist:
if set(item) & set(swap):
print "match was found", item
else:
mainlist.append(swap)
Any suggestions as to how I can test whether the next item to be added is already in the list?
Here's an approach using frozensets within a set to check for duplicates. It's a bit ugly since I'm invoking a function that works with global variables.
def add_to_mainlist(new_list):
if frozenset(new_list) not in dups:
mainlist.append(new_list)
mainlist = [['a', 'b'],['c', 'd'],['a', 'd']]
dups = set()
for l in mainlist:
dups.add(frozenset(l))
print("Before:", mainlist)
add_to_mainlist(['a', 'b'])
print("After:", mainlist)
This outputs:
Before: [['a', 'b'], ['c', 'd'], ['a', 'd']]
After: [['a', 'b'], ['c', 'd'], ['a', 'd']]
Showing that the new list was indeed not added to the original.
Here's a cleaner version that calculates the existing set on the fly inside a function that does everything locally:
def add_to_mainlist(mainlist, new_list):
dups = set()
for l in mainlist:
dups.add(frozenset(l))
if frozenset(new_list) not in dups:
mainlist.append(new_list)
return mainlist
mainlist = [['a', 'b'],['c', 'd'],['a', 'd']]
print("Before:", mainlist)
mainlist = add_to_mainlist(mainlist, ['a', 'b']) # the assignment isn't needed, but done anyway :-)
print("After:", mainlist)
Why doesn't your existing code work?
This is what you're doing:
...
for item in mainlist:
if set(item) & set(swap):
print "match was found", item
else:
mainlist.append(swap)
You're intersecting two sets and checking the truthiness of the result. While this might be okay for 0 intersections, in the event that even one of the elements are common (example, ['a', 'b'] and ['b', 'd']), you'd still declare a match which is false.
Ideally you'd want to check the length of the resultant set and make sure its length is equal to than 2:
dups = False
for item in mainlist:
if len(set(item) & set(swap)) == 2:
dups = True
break
if dups == False:
mainlist.append(swap)
You'd also ideally want a flag to ensure that you did not find duplicates. Your previous code would add without checking all items first.
If the order of your inner lists doesn't matter, then this can trivially be accomplished using frozenset()s:
>>> mainlist = [['a', 'b'],['c', 'd'],['a', 'd']]
>>> mainlist = [frozenset(sublist) for sublist in mainlist]
>>>
>>> def add_to_list(lst, sublist):
... if frozenset(sublist) not in lst:
... lst.append(frozenset(sublist))
...
>>> mainlist
[frozenset({'a', 'b'}), frozenset({'d', 'c'}), frozenset({'a', 'd'})]
>>> add_to_list(mainlist, ['b', 'a'])
>>> mainlist
[frozenset({'a', 'b'}), frozenset({'d', 'c'}), frozenset({'a', 'd'})]
>>>
If the order does matter you can either do what #Coldspeed suggested - Construct a set() from your list, construct a frozenset() from the list to be added, and test for membership - or you can use all() and sorted() to test if the list to be added is equivalent to any of the other lists:
>>> def add_to_list(lst, sublist):
... for l in lst:
... if all(a == b for a, b in zip(sorted(sublist), sorted(l))):
... return
... lst.append(sublist)
...
>>> mainlist
[['a', 'b'], ['c', 'd'], ['a', 'd']]
>>> add_to_list(mainlist, ['b', 'a'])
>>> mainlist
[['a', 'b'], ['c', 'd'], ['a', 'd']]
>>>

Combining two lists ( so [['a', 'b'], ['c', 'd']] = ['ac', 'ad', 'bc', 'bd] ) the pythonic way [duplicate]

This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 8 years ago.
Given a list of lists such as:
[['a', 'b'], ['c', 'd'], ['e']]
Result should be:
['ace', 'ade', 'bce', 'bde']
The nested lists will be different lengths. Order must be maintained -- i.e. first letter must come from first list, second letter from second list, etc.
Here is my current, recursive solution:
def combine_letters(l)
if len(l) == 0:
return l[0]
temp = [x + y for x in l[0] for y in l[1]]
new = [temp] + l[2:]
return combine_letters(new)
However, I feel like there should be a quick, maybe even one line, way to do this, possible using the reduce function. Any thoughts?
Thank you!
Edit: this is not exactly analogous to the linked question. First, it is for a arbitrarily large number of sublists. Second, it returns strings rather than tuples.
>>> L = [['a', 'b'], ['c', 'd'], ['e']]
>>> import itertools
>>> list(itertools.product(*L))
[('a', 'c', 'e'), ('a', 'd', 'e'), ('b', 'c', 'e'), ('b', 'd', 'e')]
>>> list(''.join(tup) for tup in list(itertools.product(*L)))
['ace', 'ade', 'bce', 'bde']

Categories

Resources