Compare lists in the same dictionary of lists - python

In resume, I have two keys in the same dictionary where each one has their corresponding lists.
I try to compare both list to check common and differential elements. It means that the output I will count how many elements are identical or present in only one key's list.
from the beginning I am inserting the elements using the files as arguments and they are read in the function
def shared(list):
dict_shared = {}
for i in list:
infile = open(i, 'r')
if i not in dict_shared:
dict_shared[i] = []
for line in infile:
dict_shared[spacer].append(record.id)
return dict_shared
Now I am stuck trying to find a way to compare the lists created and present in the dictionary.
dict = {a:[1,2,3,4,5], b:[2,3,4,6]}
My intention is to compare the lists in order to have the lines shared between two texts.
a: [1,5]
b: [6]
a-b: [2,3,4]
From now I can't find a way to solve this. Any suggestion?

You could use set:
d = {'a':[1,2,3,4,5], 'b':[2,3,4,6]}
print(list(set(d['a'])-set(d['b'])))
print(list(set(d['b'])-set(d['a'])))
print(list(set(d['b'])&set(d['a'])))
result:
[1, 5]
[6]
[2, 3, 4]

you can do that by utilising python inbuilt functions like union, difference, intersection.
Note: These are for sets,
you can convert a list to set by
1stset = set(a)
example:
print(1stset.difference(2ndset))
print(1stset.intersection(2ndset))
print(1stset.union(2ndset))
you can refer the following links for more information
https://www.geeksforgeeks.org/python-intersection-two-lists/
https://www.geeksforgeeks.org/python-union-two-lists/
https://www.geeksforgeeks.org/python-difference-two-lists/

A solution with list comprehension would be:
dictionary = {'a':[1,2,3,4,5], 'b':[2,3,4,6]}
only_in_a = [x for x in dictionary['a'] if not x in dictionary['b']]
only_in_b = [x for x in dictionary['b'] if not x in dictionary['a']]
in_both = [x for x in dictionary['a'] if x in dictionary['b']]
Note that this is not especially wise in terms of complexity, for larger lists.

Not sure if I understand correctly what you are trying to achieve but it seems like you'd need set operations:
dictionary = {"a":[1,2,3,4,5], "b":[2,3,4,6]}
#in a but not in b
set(dictionary["a"]) - set(dictionary["b"])
#in b but not in a
set(dictionary["b"]) - set(dictionary["a"])
#union of both
set(dictionary["b"]).union(set(dictionary["a"]))
#intersection of both
set(dictionary["b"]).intersection(set(dictionary["a"]))

You can try something like this
mydict = {'a': [1,2,3,4,5], 'b': [2,3,4,6]}
>>> list(set(mydict['a']).intersection(mydict['b'])) # common to both
[2, 3, 4]
>>> list(set(mydict['a']).difference(mydict['b'])) # a - b
[1, 5]
>>> list(set(mydict['b']).difference(mydict['a'])) # b - a
[6]
>>> list(set(mydict['a']).union(mydict['b'])) # union of both
[1, 2, 3, 4, 5, 6]

Try this
print("a - b : {} ".format(list(set(_dict['a']) - set(_dict['b']))))
print('b - a : {} '.format(list(set(_dict['b']) - set(_dict['a']))))
print('a \u2229 b : {} '.format(list(set(_dict['a']).intersection(set(_dict['b'])))))
Output
a - b : [1, 5]
b - a : [6]
a ∩ b : [2, 3, 4]

Related

Filter nested list with list comprehension based on other list in python

I have two lists like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
I would now like to filter list a, to keep only the items which contain the items in list b. So the desired output would look like this:
[[1,2,3],[2,3,4]]
I have tried some nested list comprehensions, which I could think of, but could not get the desired output. Any advice is appreciated.
you could try something like this :
print([i for i in a if any(map(i.__contains__,b))])
>>> [[1, 2, 3], [2, 3, 4]]
I would try something like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
result = [lst for lst in a if any(x in lst for x in b)]
A combination of list comprehension and sets would yield the wanted result. Note; I assume that repeated items and ordering is not of interest, if this is the case - a set won't work since it ignores ordering and only allows unique items.
A simple list comprehension would do, like below
filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]
There's mainly one interesting part of this list comprehension, namely the if not set(sublist).isdisjoint(filter_items). Here you only keep the sublist if the set of sublist is not disjoint of the set filter_items i.e. none of the filter_items is in the sublist.
for your given example the provided answer would yield the following:
>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]
Using a set approach the in can be mimic with an intersection:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
b_as_set = set(b)
out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]
I would try something like this.
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
print([lst for lst in a if any([item in b for item in lst])])

Remove multiple values from 2 lists, but only once, in Python

I have two lists:
A = [5,5,4,3]
B = [5,1]
I want to remove values that appear in both lists, but only once, i.e. output should be:
Aprime = [5,4,3]
Bprime = [1]
I understand that a good way to get the difference is with sets, but this removes all repeats, not just once
You can create collections.Counter objects with the input lists and obtain the differences of the two:
from collections import Counter
a = Counter(A)
b = Counter(B)
Aprime = list((a - b).elements()) # Aprime becomes: [5, 4, 3]
Bprime = list((b - a).elements()) # Bprime becomes: [1]
Use sets to find the duplicates, but then remove them once from the original lists.
dups = set(A).intersection(set(B))
for dup in dups:
A.remove(dup)
B.remove(dup)
You can remove from each of the counters associate to A and B the Counter build using the set of the two lists so that they are only considered once.
>>> A = [5,5,5,1,1]
>>> B = [5,1,1]
>>> a_new = list((Counter(A) - Counter(set(B))).elements())
>>> b_new = list((Counter(B) - Counter(set(A))).elements())
>>> a_new
[5, 5, 1]
>>> b_new
[1]

Lists, how to add multiple values at one time

i just wondered if there is a way to append at one time multiple values i.e.
defining an function with the parameter x, that will automaticly append the amount of elements definied by an x.
def Append(x):
L = []
L.append(x - Elements)
return L
Thanks in advance
Try this to append several similar values to an existing list:
>>> l = [1,2]
>>> l += [3]*2
>>> l
[1, 2, 3, 3]
.extend() list method works too
>>> l = [1,2]
>>> l.extend([3]*2)
>>> l
[1, 2, 3, 3]
i meant it to add an x-Amount of Elements, not an specific one but just for example: Append(20) -> Should add 20 new elements

remove non repeating characters from a list

I am trying to remove non repeating characters from a list in python. e.g list = [1,1,2,3,3,3,5,6] should return [1,1,3,3].
My initial attempt was:
def tester(data):
for x in data:
if data.count(x) == 1:
data.remove(x)
return data
This will work for some inputs, but for [1,2,3,4,5], for example, it returns [2,4]. Could someone please explain why this occurs?
l=[1,1,2,3,3,3,5,6]
[x for x in l if l.count(x) > 1]
[1, 1, 3, 3, 3]
Adds elements that appear at least twice in your list.
In your own code you need to change the line for x in data to for x in data[:]:
Using data[:] you are iterating over a copy of original list.
There is a linear time solution for that:
def tester(data):
cnt = {}
for e in data:
cnt[e] = cnt.get(e, 0) + 1
return [x for x in data if cnt[x] > 1]
This is occurring because you are removing from a list as you're iterating through it. Instead, consider appending to a new list.
You could also use collections.Counter, if you're using 2.7 or greater:
[a for a, b in collections.Counter(your_list).items() if b > 1]
Another linear solution.
>>> data = [1, 1, 2, 3, 3, 3, 5, 6]
>>> D = dict.fromkeys(data, 0)
>>> for item in data:
... D[item] += 1
...
>>> [item for item in data if D[item] > 1]
[1, 1, 3, 3, 3]
You shouldn't remove items from a mutable list while iterating over that same list. The interpreter doesn't have any way to keep track of where it is in the list while you're doing this.
See this question for another example of the same problem, with many suggested alternative approaches.
you can use the list comprehention,just like this:
def tester(data):
return [x for x in data if data.count(x) != 1]
it is not recommended to remove item when iterating

Concatenate List Object Name with a Number and Retain the List Python

I'm using python 2.7 I'm trying to figure out a way to change the names of my lists automatically.
Let me explain i have multiple lists
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 9, 3]
list3 = [8, 4, 3, 2, 1]
I would like to call the lists in a loop to determine which lists contain or do not contain a particular number.
My first thought was
x = "list" + str(i) # (where i iterates in the loop)
print x
However, using the above code only gave me the string "list1"(when i=1).
What I want is to be able to call the list that is named list1 and use the .count() operator to determine whether or not the number exists if it doesn't i want to call the next list until I'm out of lists(there will eventually be up to 30 lists).
Thanks,
Ryan
You shouldn't approach it like this. Put your lists in a container to iterate over them instead:
In [5]: for l in (list1, list2, list3):
...: print l.count(2)
...:
1
0
1
What you could do in a real-life use case is create a list of lists and fill it dynamically.
Then to get the first list that contains a given number, you could do:
In [6]: lists = [list1, list2, list3]
In [7]: next(l for l in lists if 9 in l)
Out[7]: [4, 5, 9, 3]
put the list in dict:
list1 = [1,2.4]
list2 = [2,5,6]
dlist = {1:list1,2:list2}
for k in dlist:
print dlist[k]

Categories