Check which items exist in all sublists [duplicate] - python

This question already has answers here:
How to find common elements in list of lists?
(7 answers)
Closed 3 years ago.
I would like to collect all the items that exist in every sublist.
Let's say the list of lists looks like this:
list[0] = ['A', 'B', 'C', 'D']
list[1] = ['X', 'B', 'A']
list[2] = ['R', 'C', 'A', 'B', 'X']
'A' and 'B' exist in every sublist and my goal is to save these to another list:
list2 = ['A', 'B']
I've been trying to use list comprehension but I can't figure out how to get it to work the way I want. Any help is greatly appreciated!

If order doesn't matter, you can use set.intersection:
l = [['A', 'B', 'C', 'D'],
['X', 'B', 'A'],
['R', 'C', 'A', 'B', 'X']]
list2 = list(set.intersection(*(set(sl) for sl in l)))
print(list2)
Output:
['A', 'B']
# or ['B', 'A']

Use set intersections, and then convert the result back to a list.
your_list = [
['A', 'B', 'C', 'D'],
['X', 'B', 'A'],
['R', 'C', 'A', 'B', 'X']
]
print(set.intersection(*map(set,your_list)))
If you know the values per list are unique in the first place, and you don't care about order, then you can just use a list of sets in your original code, so this simplifies to:
your_list = [
set(['A', 'B', 'C', 'D']),
set(['X', 'B', 'A']),
set(['R', 'C', 'A', 'B', 'X'])
]
print(set.intersection(*your_list))
Note don't call your own variables list, as it collides with the built-in list type and will get really confusing.

Try this :
>>> list1 = [['A', 'B', 'C', 'D'], ['X', 'B', 'A'], ['R', 'C', 'A', 'B', 'X']]
>>> list2 = list(set(list1[0]).intersection(list1[1]).intersection(list1[2]))
>>> list2
['A', 'B']

Related

remove lists with same elements but in different order, from a list of lists

I want to filter a list of lists for duplicates. I consider two lists to be a duplicate of each other when they contain the same elements but not necessarily in the same order. So for example
[['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
should become
[['A', 'B', 'C'], ['D', 'B', 'A']]
since ['C', 'B', 'A'] is a duplicate of ['A', 'B', 'C'].
It does not matter which one of the duplicates gets removed, as long as the final list of lists does not contain any duplicates anymore. And all lists need to keep the order of there elements. So using set() may not be an option.
I found this related questions:
Determine if 2 lists have the same elements, regardless of order? ,
How to efficiently compare two unordered lists (not sets)?
But they only talk about how to compare two lists, not how too efficiently remove duplicates. I'm using python.
using dictionary comprehension
>>> data = [['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
>>> result = {tuple(sorted(i)): i for i in data}.values()
>>> result
dict_values([['C', 'B', 'A'], ['D', 'B', 'A']])
>>> list( result )
[['C', 'B', 'A'], ['D', 'B', 'A']]
You can use frozenset
>>> x = [['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
>>> [list(s) for s in set([frozenset(item) for item in x])]
[['A', 'B', 'D'], ['A', 'B', 'C']]
Or, with map:
>>> [list(s) for s in set(map(frozenset, x))]
[['A', 'B', 'D'], ['A', 'B', 'C']]
If you want to keep the order of elements:
data = [['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
seen = set()
result = []
for obj in data:
if frozenset(obj) not in seen:
result.append(obj)
seen.add(frozenset(obj))
Output:
[['A', 'B', 'C'], ['D', 'B', 'A']]
Do you want to keep the order of elements?
from itertools import groupby
data = [['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
print([k for k, _ in groupby(data, key=sorted)])
Output:
[['A', 'B', 'C'], ['A', 'B', 'D']]
In python you have to remember that you can't change existing data but you can somehow append / update data.
The simplest way is as follows:
dict = [['A', 'B', 'C'], ['C', 'B', 'A'], ['D', 'B', 'A']]
temp = []
for i in dict:
if sorted(i) in temp:
pass
else:
temp.append(i)
print(temp)
cheers, athrv

Combination of elements in a list with constraints

I am writing a python code and I need help with a task. I have a list of 8 elements
[A,B,C,D,E,F,G,H]
and I need to find all the combinations of shorter lists (4 elements) in lexicographic order such that two elements are taken from the subset A,C,E,G and the other two from B,D,F,H. I know that there is the library itertools, but I don't know how to combine its functions properly to perform this task
The wording of the question is unclear, but I think this is what you want:
array = ['f','g','d','e','c','b','h','a']
first = sorted(array[::2]) # ['c', 'd', 'f', 'h']
second = sorted(array[1::2]) # ['a', 'b', 'e', 'g']
I think this is what you want.
I need the set of all the new lists with length 4 such that the first two elements are taken from A,C,E,G and the other two are from B,D,F,H and I need them to be in lexicographic order.
We get the possible starting letters and ending letters then combine all possible pairs of each of them into all_lists:
from itertools import combinations
lst = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
starters = lst[::2] # ['A', 'C', 'E', 'G']
enders = lst[1::2] # ['B', 'D', 'F', 'H']
all_lists = []
for a in combinations(starters, 2):
for b in combinations(enders, 2):
all_lists.append(sorted(a + b))
print(all_lists) # Gives [['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'F'], ['A', 'B', 'C', 'H'], ['A', 'C', 'D', 'F'], ['A', 'C', 'D', 'H'], ['A', 'C', 'F', 'H'], ...
print(all_lists == sorted(all_lists)) # False now
(Updated to sort each mini-list.)
Come to think of it you could maybe do the second part with itertools.product.

How do i subtract two lists with non-unique elements in Python? [duplicate]

This question already has answers here:
Subtracting two lists in Python
(13 answers)
Difference Between Two Lists with Duplicates in Python
(6 answers)
Closed 2 years ago.
Let's say I have two lists like:
list1 = ['a', 'c', 'a', 'b']
list2 = ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'd', 'e', 'f']
list_final = list2 - list1
list_final = ['a', 'a', 'c', 'd', 'e', 'f']
I don't think the approach of set(lists) and using .difference would help because its not a unique set.
Any sort of help would be greatly appreciated and im new to the language so any and all answers/tips are welcome!
If the order is not important, you can make Counters from the lists and subtract them.
from collections import Counter
list1 = ['a', 'c', 'a', 'b']
list2 = ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'd', 'e', 'f']
final = Counter(list2) - Counter(list1)
print(list(final.elements())) # -> ['a', 'a', 'c', 'd', 'e', 'f']
It's being used as a multiset.
There are some caveats to "order is not important", like the fact that dicts in Python 3.7+ will preserve insertion order, hence why the output here is ordered.
list.remove should be enough here, even though not the most efficient way of doing it as .remove has a O(n) complexity.
list1 = ['a', 'c', 'a', 'b', 'k']
list2 = ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'd', 'e', 'f']
for e in list1:
try:
list2.remove(e)
except ValueError:
print(f'{e} not in list')
list2
# ['a', 'a', 'c', 'd', 'e', 'f']

Python List Column Move

I'm trying to move the second value in a list to the third value in a list for each nested list. I tried the below, but it's not working as expected.
Code
List = [['a','b','c','d'],['a','b','c','d'],['a','b','c','d']]
print(List)
col_out = [List.pop(1) for col in List]
col_in = [List.insert(2,List) for col in col_out]
print(List)
Result
[['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']]
[['a', 'b', 'c', 'd'], [...], [...]]
Desired Result
[['a', 'c', 'b', 'd'], ['a', 'c', 'b', 'd'], ['a', 'c', 'b', 'd']]
UPDATE
Based upon pynoobs comment, i came up with the following. But i'm still not there. Why is 'c' printing?
Code
List = [['a','b','c','d'],['a','b','c','d'],['a','b','c','d']]
col_out = [col.pop(1) for col in List for i in col]
print(col_out)
Result
['b', 'c', 'b', 'c', 'b', 'c']
[List.insert(2,List) for col in col_out]
^^^^ -- See below.
You are inserting an entire list as an element within the same list. Think recursion!
Also, please refrain from using state-changing expressions in list comprehension. A list comprehension should NOT modify any variables. It is bad manners!
In your case, you'd do:
lists = [['a','b','c','d'],['a','b','c','d'],['a','b','c','d']]
for lst in lists:
lst[1], lst[2] = lst[2], lst[1]
print(lists)
Output:
[['a', 'c', 'b', 'd'], ['a', 'c', 'b', 'd'], ['a', 'c', 'b', 'd']]
You can do it like this
myList = [['a','b','c','d'],['a','b','c','d'],['a','b','c','d']]
myOrder = [0,2,1,3]
myList = [[sublist[i] for i in myOrder] for sublist in myList]

How to move values in a list one by one? [duplicate]

This question already has an answer here:
Moving values but preserving order in a Python list [duplicate]
(1 answer)
Closed 8 years ago.
I'm learning python, and am trying to move values in a list in loop. But dont know how to do it. So, if I have this:
list1 = ['a', 'b', 'c', 'd']
How can i rotate the values to right by one and get
['d', 'a', 'b', 'c']
and then move again
[ 'c', 'd', 'a', 'b']?
Just use list slice notation:
>>> list1 = ['a', 'b', 'c', 'd']
>>> list1[:-1]
['a', 'b', 'c']
>>> list1[-1:]
['d']
>>> list1[-1:] + list1[:-1]
['d', 'a', 'b', 'c']
>>> def rotate(lst):
... return lst[-1:] + lst[:-1]
...
>>> list1
['a', 'b', 'c', 'd']
>>> list1 = rotate(list1)
>>> list1
['d', 'a', 'b', 'c']
>>> list1 = rotate(list1)
>>> list1
['c', 'd', 'a', 'b']
The easiest why would be to use deque.
from collections import deque
d = deque(list1)
d.rotate(1)
print(d)
d.rotate(1)
print(d)
Gives:
deque(['d', 'a', 'b', 'c'])
deque(['c', 'd', 'a', 'b'])

Categories