Python: Count Values in multi-value Dictionary - python

How can I count the number of a specific values in a multi-value dictionary?
For example, if I have the keys A and B with different sets of numbers as values, I want get the count of each number amongst all of the dictionary's keys.
I've tried this code, but I get 0 instead of 2.
dic = {'A':{0,1,2},'B':{1,2}}
print(sum(value == 1 for value in dic.values()))

Counter is a good option for this, especially if you want more than a single result:
from collections import Counter
from itertools import chain
from collections import Counter
count = Counter(chain(*(dic.values())))
In the REPL:
>>> count
Counter({1: 2, 2: 2, 0: 1})
>>> count.get(1)
2
Counter simply tallies each item in a list. By using chain we treat a list of lists as simply one large list, gluing everything together. Feeding this right to Counter does the work of counting how many of each item there is.

Related

Displays in order the most common items in a list with the index name

I would like to use something like the frequency vector and also display the most common indexes in a list and how many times they meet and make a top of it
I have something like this now but I don't know how I could count on it
from collections import Counter
class AttributesCount:
#staticmethod
def count():
object = [
{"width":"32"},
{"color":"red"},
{"color:":"red"},
{"color":"black"},
{"color":"orange"},
{"color":"red"}]
for i in object:
print(AttributesCount.count())
I've seen all kinds of count functions, collections but I want exactly what I said above, to make a top
How can I do this?
from collections import Counter I tried with this but I is not correctly
Your intuition to use a Counter is correct.
Given a list of dictionaries with the variable name attribute_list, we first populate the Counter.
We can loop over the keys of each dictionary in the list and add 1 to each count, but we can be more succinct using Counter's update method.
Then we can call Counter's most_common method to return a list of tuples in descending frequency:
>>> from collections import Counter
>>> frequencies = Counter()
>>> for attribute in attribute_list:
... frequencies.update(attribute.keys())
...
>>> frequencies
Counter({'width': 1, 'color': 4, 'color:': 1})
>>> frequencies.most_common()
[('color', 4), ('width', 1), ('color:', 1)]

How do you check if a list's item is equal to another item in the same list

I understand the basics of this problem however I need help on how I can do this the most efficient way possible (taking the least amount of time for the programmer however not substituting stability of the code or efficiency).
Let's say we have a string:
grades=str(input("Enter a string"))
in my code, I would join a space between all characters in the string above and then split the characters into separate items in the same list:
grades=" ".join(grades)
grades.split(" ")
I then want to use loops of some sort to search the list for repeating items. However, I want to learn how I can do this the most efficient way possible:
x=len(grades)
for i in range(0, x):
if grades[i] == # here is were I'm having trouble
I want to know how I can search whether 1 item in the list is equal to any item in the whole list itself. Kind regards.
I make an example:
from collections import Counter
a =[1,2,3,4,1,2]
c = Counter(a)
for k,v in c.items():
if v>1:
print(k,'repeated more than once')
Here the c will be a Counter object like this Counter({1: 2, 2: 2, 3: 1, 4: 1}). the keys are the array values and values are the count of them.
So I write the for for your understanding. You can do anything with c, it acts like a dict.
>> [k for k,v in c.items() if v>1]
[1, 2]

Python3: Integer not repeated

Out of a random list of integers, with integers being repeated in the list, what is the way to print that integer out of the list which is not repeated at all?
I have tried to solve the question by making the following program:
K = int(input())
room_list = list(input().split())
room_set = set(room_list)
for i in room_set:
count = room_list.count(i)
if count == 1:
i = int(i)
print(i)
break
K being the number of the elements in the list.
When I try to run the above program, it works well in the case of less elements however, when it is tested with a list having (say, 825) elements, the program times out.
Please help me in optimizing the above code.
Elements whose repetition count in the list is one will be your answer.
from collections import Counter
a = [1,1,1,2,2,3,4,5,5]
c = Counter(a) # O(n)
x = [key for key, val in c.items() if val == 1]
print(x)
Output:
[3,4]
Counter class creates a dictionary of elements and repetitions by iterating through the list once that takes time O(n) and each element's access takes O(1) time.
The count function of the list iterates every time you call it on a list. In your case taking O(n^2) time.
This will print the number that occured least often:
data = [3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,93,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]
from collections import Counter
# least often
print (Counter(data).most_common()[-1][0])
# all non-repeated onces
# non_repeat = [k[0] for k in Counter(data).most_common() if k[1] == 1]
Output:
93
It uses a specialized dictionary: collection.Counter thats built for counting things in iterable you give it.
The method .most_common() returns a sorted list of tuples of (key, count) - by printing its last member you get the one thats least often.
The built-up dict looks like this:
Counter({4: 4, 5: 4, 6: 4, 7: 4, 8: 4, 3: 3, 9: 3, 0: 2, 1: 2, 2: 2, 93: 1})
A similar approach is to use a collections.defaultdict and count them yourself, then get the one with the minimal value:
from collections import defaultdict
k = defaultdict(int)
for elem in data:
k[elem] += 1
print( min(k.items(), key=lambda x:x[1]) )
The last solutions is similar in approach without the specialized Counter - the advantage of both of them is that you iterate once over the whole list and increment a value instead of iterating n times over the whole list and count each distinct elements occurences once.
Using count() on a list of pure distinct elements would lead to n counting-runs through n elements = n^2 actions needed.
The dictionary approach only needs one pass though the list so only n actions needed.

python list of sets find symmetric difference in all elements

Consider this list of sets
my_input_list= [
{1,2,3,4,5},
{2,3,7,4,5},
set(),
{1,2,3,4,5,6},
set(),]
I want to get the only exclusive elements 6 and 7 as the response, list or set. Set preferred.
I tried
print reduce(set.symmetric_difference,my_input_list) but that gives
{2,3,4,5,6,7}
And i tried sorting the list by length, smallest first raises an error due to two empty sets. Largest first gives the same result as unsorted.
Any help or ideas please?
Thanks :)
Looks like the most straightforward solution is to count everything and return the elements that only appear once.
This solution uses chain.from_iterable (to flatten your sets) + Counter (to count things). Finally, use a set comprehension to filter elements with count == 1.
from itertools import chain
from collections import Counter
c = Counter(chain.from_iterable(my_input_list))
print({k for k in c if c[k] == 1})
{6, 7}
A quick note; the empty literal {} is used to indicate an empty dict, not set. For the latter, use set().
You could use itertools.chain and collection.Counter:
from itertools import chain
from collections import Counter
r = {k for k,v in Counter(chain.from_iterable(my_input_list)).items() if v==1}

Matching/Counting lists in python dictionary

I have a dictionary {x: [a,b,c,d], y: [a,c,g,f,h],...}. So the key is one variable with the value being a list (of different sizes).
My goal is to match up each list against every list in the dictionary and come back with a count of how many times a certain list has been repeated.
I tried this but does not seem to work:
count_dict = {}
counter = 1
for value in dict.values():
count_dict[dict.key] = counter
counter += 1
You could map the lists to tuples so they can be used as keys and use a Counter dict to do the counting:
from collections import Counter
count = Counter(map(tuple, d.values()))

Categories