Python: How to aggregate and count identical values in a Dictionary - python

I'm using a defaultdict from Python's collections:
from collections import defaultdict
data = defaultdict(list)
Within the dictionary I have a set of key/list. Example:
{1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
I'm looking for a way to count how many times each list (identical order and content) is found in the dictionary. Basically, I need to aggregate each list with a counter.
For example, the combination [1, 6, 3, 4, 5] is found 2 times.
Is there any helper class/function that can do it? Other than that, I'd just create a double for loop across the dictionary.
Thanks!

Try this:
from collections import Counter
data = defaultdict(list, {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
c = Counter(map(tuple, data.values()))
print(c)
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})

H = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
occurences = dict()
for i in H.keys() :
k = 0
for j in H.keys():
if H[j] == H[i] :
k += 1
if i not in occurences.keys():
occurences[i] = k

Use collections.Counter
>>> from collections import Counter
>>> d = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
>>> print(Counter(tuple(l) for l in d.values())
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})
You'll have to convert your lists to tuples, because Counters can't count unhashable (mutable) types.

Related

Function to take a list of integers and count the highest repeated value

Need a function to take a list of integers and return the highest repeated value.
For example: take [4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2] and return (2,5) because there are 5 copies of the value 2.
You can do this pretty easily using Counter.
from collections import Counter
a = [4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]
def count_duplicates(list_of_integers):
a = Counter(list_of_integers)
return a.most_common()[0]
count = count_duplicates(a)
print(count)
The output from that gives you (2, 5)
Inbuilt max, set and count methods:
def countMax(arr):
item = max(set(arr), key=arr.count)
return (item, arr.count(item))
print(countMax([4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]))
Prints (2, 5).
We can utilize tuple to keep track the highest repeated value, like so:
def find_highest_repeated(input_list):
counter = {}
highest_repeated = (0, 0, )
for item in input_list:
counter[item] = counter[item] + 1 if counter.get(item) is not None else 1
if counter[item] > highest_repeated[1]:
highest_repeated = (item, counter[item], )
return highest_repeated
find_highest_repeated([4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]) # (2, 5)
Hope that helps!
You can use defaultdict to achieve this:
from collections import defaultdict
def highest_repeated_value(nums):
cache = defaultdict(int)
for i in nums:
cache[i] += 1
return max(cache.items(), key=lambda x: x[1])
nums = [4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]
print(highest_repeated_value(nums))
Please note that if nums = [4, 4, 4, 4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2] then there are five 4s and five 2s. However, the result will be (4, 5) i.e. five 4s.
If your using numpy and list contains all non-negative ints, you can use numpy.bincounts:
import numpy
def highest_repeated_value(nums):
counts = numpy.bincount(nums)
num = numpy.argmax(counts)
val = numpy.max(counts)
return num, val
nums = [4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]
print(highest_repeated_value(nums))
If you just want to work in python without using numpy, collections.Counter is a good way to handle it.
from collections import Counter
def highest_repeated_value(nums):
return Counter(nums).most_common()[0]
nums = [4, 2, 2, 2, 8, 5, 4, 2, 9, 6, 3, 2]
print(highest_repeated_value(nums))

python updating global dict inside recursive function

I am trying to find all permutations of elements in a list and add it to a global dictionary
Code:
outp={}
k=0
def func(i,arr):
global outp
global k
arr=arr.copy()
for j in range(i,len(list)):
arr[i],arr[j] = arr[j],arr[i]
if i!=j or i==0:
k=k+1
print("\n\n",arr,k)
outp[k]=arr
print("\n",outp)
func(i+1,arr)
list = [1,2,3,8]
func(0,list)
Output below:
Till 4th element it updated correctly. During 5th element, it updated both 5th and 3rd element in the dictionary. I don't know why it is happening. Kindly help
[1, 2, 3, 8] 1
{1: [1, 2, 3, 8]}
[1, 2, 8, 3] 2
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3]}
[1, 3, 2, 8] 3
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8]}
[1, 3, 8, 2] 4
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8], 4: [1, 3, 8, 2]}
[1, 8, 2, 3] 5
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 8, 2, 3], 4: [1, 3, 8, 2], 5: [1, 8, 2, 3]}
You need to place a copy of the array in the dictionary:
outp[k] = arr.copy()
This would be a better way to copy list to a new list.
arr=arr[:] .
https://repl.it/repls/BronzeYellowConversion

Looping over list elements without for loop

I have a Python dictionary with multiple values stored as a list like this-
{'a': [1, 2, 3], 'b': [2, 3, 4], 'c': [3, 4, 5]}
I wish to create a dictionary of lists where each values becomes a key and stores the list as a value like this
if __name__=='__main__':
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=dict()
for key,value in x.items():
for i in value:
if i not in list(d.keys()):
d[i]=value
else:
d[i].extend(value)
print(d)
I get the following output-
{1: [1, 2, 3, 2, 3, 4], 2: [1, 2, 3, 2, 3, 4], 3: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4], 4: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4], 5: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4]}
I wish for the output to be like this-
{1: [1, 2, 3], 2: [2, 3, 4, 1, 2, 3], 3: [2, 3, 4, 3, 4, 5, 1, 2, 3], 4: [2, 3, 4, 3, 4, 5], 5: [3, 4, 5]}
Where is the error in my code?
I wish to avoid nested for loops as I have to iterate over a large number of values (x dictionary keys and list elements). Is there a better way to iterate over each list value without using nested loops? Should I redo the way I've stored the values (some other data type besides dictionary of lists)?
I'm looking for a solution that is computationally inexpensive in terms of time and maybe space too.
Edit:
By making a copy of the list, the code returns correct output-
if __name__=='__main__':
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=dict()
for key,value in x.items():
for i in value:
if i not in list(d.keys()):
d[i]=list(value)
else:
d[i].extend(value)
print(d)
You could use defaultdict:
from collections import defaultdict
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=defaultdict(list)
for key,value in x.items():
for i in value:
d[i] += value
Or
for value in x.values():
for i in value:
d[i] += value

How to count in a row results from text file

i would like to know how to count in a row results from text file. I wroted this code:
from itertools import groupby
def count_runs_of(seq, val):
return sum(key == val for key, group in groupby(seq))
Example:
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
1
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
2
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3, 9, 2, 4, 3, 3, 3], 3)
3
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 2)
2
I want to know how long serie it is. For example, when i have "1" in first result, i want to also print "3" (because there was 3 x 3 in a row). Could You help me? Thank You
def count_runs_of(seq, val):
return [len(list(group)) for key, group in groupby(seq) if key == val]
Example
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]
You were pretty close, you get get the length of a group by looping on it using sum() and generator expression. This will return length of all such runs in the list:
>>> def count_runs_of(seq, val):
return [sum(1 for _ in g) for k, g in groupby(seq) if k == val]
...
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
[3]
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]

Sorting a List by frequency of occurrence in a list

I have a list of integers(or could be even strings), which I would like to sort by the frequency of occurrences in Python, for instance:
a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
Here the element 5 appears 4 times in the list, 4 appears 3 times. So the output sorted list would be :
result = [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
I tried using a.count(), but it gives the number of occurrence of the element.
I would like to sort it. Any idea how to do it ?
Thanks
from collections import Counter
print [item for items, c in Counter(a).most_common() for item in [items] * c]
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or even better (efficient) implementation
from collections import Counter
from itertools import repeat, chain
print list(chain.from_iterable(repeat(i, c) for i,c in Counter(a).most_common()))
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or
from collections import Counter
print sorted(a, key=Counter(a).get, reverse=True)
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
If you prefer in-place sort
a.sort(key=Counter(a).get, reverse=True)
Using Python 3.3 and the built in sorted function, with the count as the key:
>>> a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
>>> sorted(a,key=a.count)
[2, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
>>> sorted(a,key=a.count,reverse=True)
[5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
In [15]: a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
In [16]: counts = collections.Counter(a)
In [17]: list(itertools.chain.from_iterable([[k for _ in range(counts[k])] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
Out[17]: [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Alternatively:
answer = []
for k in sorted(counts, key=counts.__getitem__, reverse=True):
answer.extend([k for _ in range(counts[k])])
Of course, [k for _ in range(counts[k])] can be replaced with [k]*counts[k].
So line 17 becomes
list(itertools.chain.from_iterable([[k]*counts[k] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
If you happen to be using numpy already, or if using it is an option, here's another alternative:
In [309]: import numpy as np
In [310]: a = [1, 2, 3, 3, 1, 3, 5, 4, 4, 4, 5, 5, 5]
In [311]: vals, counts = np.unique(a, return_counts=True)
In [312]: order = np.argsort(counts)[::-1]
In [313]: np.repeat(vals[order], counts[order])
Out[313]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
That result is a numpy array. If you want to end up with a Python list, call the array's tolist() method:
In [314]: np.repeat(vals[order], counts[order]).tolist()
Out[314]: [5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2]
Not interesting way...
a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
from collections import Counter
result = []
for v, times in sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True):
result += [v] * times
One liner:
reduce(lambda a, b: a + [b[0]] * b[1], sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True), [])
Occurrence in array and within a sets of equal size:
rev=True
arr = [6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7 ,8 ,8, 8, 2]
print arr
arr.sort(reverse=rev)
ARR = {}
for n in arr:
if n not in ARR:
ARR[n] = 0
ARR[n] += 1
arr=[]
for k,v in sorted(ARR.iteritems(), key=lambda (k,v): (v,k), reverse=rev):
arr.extend([k]*v)
print arr
Results:
[6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7, 8, 8, 8, 2]
[2, 2, 2, 2, 2, 6, 6, 6, 6, 5, 5, 5, 5, 9, 9, 9, 8, 8, 8, 4, 4, 7, 3, 1]
Dart Solution
String sortedString = '';
Map map = {};
for (int i = 0; i < s.length; i++) {
map[s[i]] = (map[s[i]] ?? 0) + 1;
// OR
// map.containsKey(s[i])
// ? map.update(s[i], (value) => ++value)
// : map.addAll({s[i]: 1});
}
var sortedByValueMap = Map.fromEntries(
map.entries.toList()..sort((e1, e2) => e1.value.compareTo(e2.value)));
sortedByValueMap.forEach((key, value) {
sortedString += key * value;
});
return sortedString.split('').reversed. Join();

Categories

Resources