how to subtract one list from another including duplicates - python

I have 2 lists
On is a big list with some elements having duplicates
super_set_list = [1,1,2,3,3,4,4,4,5,6,7,8,9]
The other is a subset of the big list, also with duplicates
sub_set_list = [1,2,3,3,4,4,6,7,9]
I want the difference, like this
diff = [1,4,5,8]
Not sure how I would go about this

You can use a Counter
super_set_list = [1,1,1,2,3,3,4,4,4,5,6,7,8,9]
sub_set_list = [1,2,3,3,4,4,6,7,9]
from collections import Counter
super_counter = Counter(super_set_list)
super_counter = Counter({1: 3, 4: 3, 3: 2, 2: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1})
For every element in sub_set_list, reduce the count in in super_counter
for item in sub_set_list:
super_counter[item]-=1
Now super_counter = Counter({1: 2, 4: 1, 5: 1, 8: 1, 2: 0, 3: 0, 6: 0, 7: 0, 9: 0})
Finally, just pick elements that have some count left (but add it that many number of times).
diff=[]
for k,v in super_counter.items():
for _ in range(v):
diff.append(k)
print(diff)
# [1, 1, 4, 5, 8]

You can loop through sub-set list and remove item in super-set list one by one as follows:
super_set_list = [1,1,2,3,3,4,4,4,5,6,7,8,9]
sub_set_list = [1,2,3,3,4,4,6,7,9]
for item in sub_set_list:
if item in super_set_list:
super_set_list.remove(item)
print(super_set_list)

Related

python nested list retrieve and print specific elements

I have a nested list that looks like this. It is supposed to represent people and their possible connections. I need to output the number in quotes along with connections they might know (numbers in the sublist with 2 or 3 after the colon along with a list of people they probably (numbers in the sublist with 4 or more after the colon),so it looks like this:
6:Might(1,3,4,7,11)
1:Might(4,6,7) Probably(11)
4:Might(1,3,6,11,12)
here is my nested list
connect_cnt = [(6, {3: 3, 4: 3, 7: 2, 13: 1, 1: 3, 11: 2, 12: 1}),
(1, {7: 3, 5: 1, 9: 2, 11: 4, 10: 1 , 2: 1, 13: 1, 3: 2, 6: 3, 4: 3, 12: 2}),
(4, {3: 2, 7: 3, 6: 3, 13: 1, 1: 3, 11: 2,12: 3, 5: 1, 2: 1, 9: 1}),
I am not sure how to go about it. I tried this for starters just to see if I could get the count but it didn't work.
final_dict
for row in range(len(connect_cnt)):
for col in range(len(connect_cnt[row])):
key,value = connect_cnt[row].split(':')
if value > 1:
final_dict[key] = value
Even if I cold just get the ones I need to print in a nested list. I am a beginner and don't have much experience with nested lists.
I'm not sure of the exact solution to your answer, but I can provide a generalized solution which you can adapt to your needs.
l = [(1, {2: 3, 4: 5}), (6, {7: 8, 9: 10})]
# to change a value
l[0][1][2] = 100 # now l = [(1, {2: 100, 4: 5}), (6, {7: 8, 9: 10})]
If this does not work for your example, please provide more information, and I will try my best to help out.
Edit:
This code should extract all key-value pairs to another dictionary, given that a dictionary are always the second element of the sub-list.
final_dict = {}
for i in l:
for j in i[1].keys():
final_dict[j] = i[j]
Edit 2:
I think I understand now. This code should do it:
for i in l:
for j in i[1].keys():
if i[1][j] <= 1:
del i[1][j]
Edit 3:
Sorry. Let me know if this works:
l2 = []
for i in l:
d = {}
for j in i[1].keys():
if i[1][j] > 1:
d[j] = i[1][j]
l2.append((i[0], d))

how to use list comprehension to print a frequency dictionary?

Let's say our test case is: solution([6, 7, 7, 8, 8, 8, 9, 10, 10], 1)
where 1 is the maximum frequency to remain in the list. Logically, this translates to an expected output of [6, 9].
My attempt at a solution:
def solution(data, n):
occurrences = dict()
for _id in data:
try:
occurrences[_id] += 1
except KeyError:
occurrences[_id] = 1
print(occurrences)
return [_id for _ in range(occurrences[_id]) for _id in occurrences if occurrences[_id] <= n]
What I am trying to accomplish with the list comprehension at the end is
for key in occurrences:
if occurrences[key] <= 1:
for _ in range(occurrences[key]):
print(key)
Unfortunately, this is the output of this test case:
>>> solution([6, 7, 7, 8, 8, 8, 9, 10, 10], 1)
{6: 1}
{6: 1, 7: 1}
{6: 1, 7: 2}
{6: 1, 7: 2, 8: 1}
{6: 1, 7: 2, 8: 2}
{6: 1, 7: 2, 8: 3}
{6: 1, 7: 2, 8: 3, 9: 1}
{6: 1, 7: 2, 8: 3, 9: 1, 10: 1}
{6: 1, 7: 2, 8: 3, 9: 1, 10: 2}
[6, 9, 6, 9]
Something has to be broken in the list comprehension that is writing 6 and 9 2 times instead of range(1).
Any idea what that could be?
Your issue is caused by the for _ in range(occurrences[_id]. The reason it causes duplication of the result is that in this comprehension
return [_id for _ in range(occurrences[_id]) for _id in occurrences if occurrences[_id] <= n]
_id is not defined inside the comprehension when you execute range(occurrences[_id]) so it takes the value that _id last had in the function, which in this case is 10 and occurrences[10] is 2, so you get 2 copies of each _id. Had you used a different variable name inside the comprehension e.g.
return [xid for _ in range(occurrences[xid]) for xid in occurrences if occurrences[xid] <= n]
you would have seen the issue because you would have got a
NameError: name 'xid' is not defined
Note you can greatly simplify your code by using a Counter:
from collections import Counter
def solution(data, n):
counts = Counter(data)
return [_id for _id, _count in counts.items() if _count <= n for _ in range(_count)]
Oh snap, so I randomly decided to try plugging in the for loops the other way around and it worked...
return [_id for _id in occurrences if occurrences[_id] <= n for _ in range(occurrences[_id])]
sorry for the trouble!

Creating a dictionary in a dictionary comprehension

I have a list with repeated values and I want to count them using a dictionary comprehension
Here is my initial attempt
number_list = [1,1,2,2,3,3,4,4,5,5]
number_count_dict = {i:1 for i in number_list}
{k: (number_count_dict[k]+1 if k in number_count_dict() else 1) for k in number_list}
Is there a way of achieving this without initialising the dictionary?
Take this example for your question:
numbers = [5,3,3,4,2]
and let us say if you would like to turn it into a dictionary where the key is the index and value is the element in the list. Then you could trt something like this:
{index:numbers[index] for index in range(0,len(numbers))}
Here's the result:
{0: 5, 1: 3, 2: 3, 3: 4, 4: 2}
This will count repetitions only (>1)
>>> from collections import Counter
>>> x=[1,1,2,2,3,3,4,4,5,5]
>>> {i:j for i,j in Counter(x).items() if i>1}
{2: 2, 3: 2, 4: 2, 5: 2}
Your question leaves out a couple of important points. What is the minimum and maximum numbers you want in the dictionary? Do you want numbers with 0 to be counted? Can you use the Counter class?
#1: Count items from 0 to len(number_list) including items with count of 0, using Counter.
>>> from collections import Counter
>>> number_list = [1,1,2,2,3,3,4,4,5,5]
>>> count = Counter(number_list)
>>> number_count_dict = {i:(count[i] if i in number_list else 0) for i in range(len(number_list))}
{0: 0, 1: 2, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 0, 8: 0, 9: 0}
#2: Count items from lowest number to highest number in list including items with count of 0, using Counter.
>>> from collections import Counter
>>> number_list = [2,2,3,3,4,4,5,5,7,7]
>>> count = Counter(number_list)
>>> number_count_dict = {i:(count[i] if i in number_list else 0) for i in range(min(number_list),max(number_list)+1)}
{2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2}
#3: Count items in list using Counter.
>>> from collections import Counter
>>> number_list = [1,1,2,2,3,3,4,4,5,5]
>>> count = Counter(number_list)
>>> number_count_dict = {i:count[i] for i in set(number_list)}
{1: 2, 2: 2, 3: 2, 4: 2, 5: 2}
#4: Count items from 0 to len(number_list) including items with count of 0, NOT using Counter.
>>> number_list = [1,1,2,2,3,3,4,4,5,5]
>>> number_count_dict = {i:number_list.count(i) for i in range(len(number_list))}
{0: 0, 1: 2, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 0, 8: 0, 9: 0}
#5: Count items from lowest number to highest number in list including items with count of 0, NOT using Counter.
>>> number_list = [2,2,3,3,4,4,5,5,7,7]
>>> number_count_dict = {i:number_list.count(i) for i in range(min(number_list),max(number_list)+1)}
{2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2}
#6: Count items in list NOT using Counter.
>>> number_list = [1,1,2,2,3,3,4,4,5,5]
>>> number_count_dict = {i:number_list.count(i) for i in set(number_list)}
{1: 2, 2: 2, 3: 2, 4: 2, 5: 2}
#7: Bonus, using a defaultdict and for loop.
from collections import defaultdict
number_list = [1,1,2,2,3,3,4,4,5,5]
number_count_dict = defaultdict(int)
for i in number_list:
number_count_list[i] += 1

Multiply counter value with corresponding counter key function in a for loop

say I got following output containing several counter objects from several lists:
for b in data:
m = np.sum(b.values())
individuals = [i for i in b.values() if i != 0]
counter = collections.Counter(individuals)
Output:
Counter({1: 10, 2: 2})
Counter({1: 19, 4: 1, 5: 1})
Counter({1: 14, 2: 4, 3: 4, 4: 2})
Counter({1: 12, 3: 5, 2: 3, 4: 2, 6: 1, 9: 1})
Counter({1: 14, 3: 4, 4: 4, 2: 3, 5: 1, 8: 1, 10: 1})
Now what I am trying to do is to raise float(i)/m to the second power for each key in the counter object,
but additionally, I need to select the corresponding counter.value() and multiply it with float(i)/m. How can I integrate a
second for loop with counter.values()?
f = np.sum( float(i)/m**2 for i in counter.keys() )

Dictionary to Sparse Vector Python

please help me on this homework:
makeA({0: 1, 2: 1, 4: 2, 6: 1, 9: 1})
the output should be like this:
[1, 0, 1, 0, 2, 0, 1, 0, 0, 1]
Try a list comprehension:
def makeA(d, default=0):
"""Converts a dictionary to a list. Pads with a default element
Examples:
>>> makeA({0: 1, 2: 1, 4: 2, 6: 1, 9: 1})
[1, 0, 1, 0, 2, 0, 1, 0, 0, 1]
>>> makeA({3: 'kos'},'')
['', '', '', 'kos']
"""
maxElem = max(d)
return [d.get(x, default) for x in range(maxElem+1)]
The first line of the function body finds the maximum key in the dict (because dict objects yield their keys when iterated over). If the maximum key is 5, you'd need an array of 6 elements [0..6].
The last line uses a list comprehension over a sequence 0 .. maxElem, and for each value of this sequence, assigns either d's value for this key or 0 if not present.
Yes, you could do the default value in list comprehension. But I think it's nicer style to let the defaultdict class do it for you. And you get more readable code to boot!! :-)
from collections import defaultdict
def makeA(d):
dd = defaultdict(int, d)
return [dd[n] for n in range(10)]
print makeA({0: 1, 2: 1, 4: 2, 6: 1, 9: 1})

Categories