Display 'Counter' results on seperate line (Python) - python

I am trying to get it so that this code:
from collections import Counter
a = input('Votes: ')
a = a.split(',')
count = Counter(a)
print (count)
When I input something like this:
One,One,Two,Two,Three,Four,Five,Five
prints this:
One: 2
Two: 2
Three: 1
Four: 1
Five:2
instead of this:
Counter({'One': 2, 'Two': 2, 'Five': 2, 'Three': 1, 'Four': 1})

Loop over the Counter.most_common() output:
for key, c in count.most_common():
print("{}: {}".format(key, c))
The most_common() method gives you the items in sorted order, from most to least common:
If you need to order them by their 'came first' ordering in a (so One before Two simply because One was mentioned first) then sort them by their string index with str.index().
for key, c in sorted(count.items(), key=lambda i: a.index(i[0])):
print("{}: {}".format(key, c))
If you needed to order them by the ordinal interpretation of the numbers, use a dictionary translating words to digits:
numbers = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5} # expand as needed
for key, c in sorted(count.items(), key=lambda i: numbers[i[0].lower()]):
print("{}: {}".format(key, c))
Demo:
>>> from collections import Counter
>>> a = 'One,One,Two,Two,Three,Four,Five,Five'.split(',')
>>> count = Counter(a)
>>> for key, c in count.most_common():
... print("{}: {}".format(key, c))
...
Five: 2
Two: 2
One: 2
Three: 1
Four: 1
>>> for key, c in sorted(count.items(), key=lambda i: a.index(i[0])):
... print("{}: {}".format(key, c))
...
One: 2
Two: 2
Three: 1
Four: 1
Five: 2
>>> numbers = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5}
>>> for key, c in sorted(count.items(), key=lambda i: numbers[i[0].lower()]):
... print("{}: {}".format(key, c))
...
One: 2
Two: 2
Three: 1
Four: 1
Five: 2

from collections import Counter
a = input('Votes: ')
a = a.split(',')
count = Counter(a)
for key in sorted(set(a),key=lambda x: a.index(x)):
print ("{}: {}".format(key,count[key]))
In [13]: for key in sorted(set(a),key=lambda x: a.index(x)):
....: print ("{}: {}".format(key,count[key]))
....:
One: 2
Two: 2
Three: 1
Four: 1
Five: 2
Make a set to remove the duplicates and use sorted with a lambda to sort based on the index of the corresponding value in the a list which matches the input order

One liner, sorted:
a = ['One','One','Two','Two','Three','Four','Five','Five']
counts = Counter(a)
print('\n'.join('{}: {}'.format(*x) for x in sorted(counts.items(), key=lambda x: a.index(x[0]))))

Related

Retrieve the first element from Counter in O(n) time

I have such a nums list
In [72]: nums
Out[72]: [4, 1, 2, 1, 2]
try to get the unique number from the list
n [72]: nums
Out[72]: [4, 1, 2, 1, 2]
In [73]: c = Counter(nums)
In [74]: c
Out[74]: Counter({4: 1, 1: 2, 2: 2})
I can see the result from the counter, it is 4:1, but cannot retrieve it in O(1) time
In [79]: list(c)[0]
Out[79]: 4 #O(n) time
Is it possible to get 4 in O(1)time
According to the comments to the question, you want to get the elements that have a count of 1. But it is still not clear what you want to get exactly, as the term "the first element" is unclear in the context of a Counter, which is a dict and no defined order internally.
Here are a few options (I used str instead of int to make it clearer which are the values and which are their counts):
>>> import collections
>>> input_str = 'awlkjelqkdjlakd'
>>> c = collections.Counter(input_str)
>>> c
Counter({'l': 3, 'k': 3, 'a': 2, 'j': 2, 'd': 2, 'w': 1, 'e': 1, 'q': 1})
Get all elements that have count of 1 (takes O(k), where k is the number of different elements):
>>> [char for char, count in c.items() if count == 1]
['w', 'e', 'q']
Get one (random, not specified) element that has count of 1 (takes O(k), because the list has to be built):
>>> [char for char, count in c.items() if count == 1][0]
'w'
This can be improved by using a generator, so the full list will not be built; the generator will stop when the first element with count 1 is found, but there is no way to know if that will be first or last or in the middle ...
>>> g = (char for char, count in c.items() if count == 1)
>>> g
<generator object <genexpr> at 0x7fd520e82f68>
>>> next(g)
'w'
>>> next(char for char, count in c.items() if count == 1)
'w'
Now, if you want to find the count of the first element of your input data (in my example input_str), that is done in O(1) because it is a list item access and then a dict lookup:
>>> elem = input_str[0]
>>> elem
'a'
>>> c[elem]
2
But I cannot give a more concrete answer without more information on what exactly you need.

Binary digits string manipulation in Python

How do I calculate unique counts of (groups) of 1's and 0's in a string in Python 3? e.g.
'11110000110110001111011'
Output should be
{0:{1, 3, 4} , 1:{2, 4}}
You can use itertools.groupby and add the length of each group to a dict of sets:
from itertools import groupby
s = '11110000110110001111011'
d = {}
for k, g in groupby(s):
d.setdefault(int(k), set()).add(sum(1 for _ in g))
d becomes:
{1: {2, 4}, 0: {1, 3, 4}}
You could do this with while loop, by adding difference of index of first character opposite to that on current index and that idx, to some list, here values of counted_x.
x = '11110000110110001111011'
counted_x = {'0': [], '1': []}
idx = 0
while idx < len(x):
oposite_key = str(abs(int(x[idx])-1))
if oposite_key in x[idx:]:
counted_x[x[idx]].append(x.index(oposite_key, idx) - idx)
else:
counted_x[x[idx]].append(len(x[idx:]))
idx += counted_x[x[idx]][-1]
counted_x = [{k: list(set(v))} for k, v in counted_x.items()]
print(counted_x)
Output:
[{'0': [1, 3, 4]}, {'1': [2, 4]}]

Count the same list's occur frequency in a multi-dimensional list?

I have a multi-dimensional list as like below
multilist = [[1,2],[3,4,5],[3,4,5],[5,6],[5,6],[5,6]]
How can I get below results fast:
[1,2]: count 1 times
[3,4,5]: count 2 times
[5,6]: count 3 times
and also get the unique multi-dimensional list (remove duplicates) :
multi_list = [[1,2],[3,4,5],[5,6]]
Thanks a lot.
You can use tuples which are hashable and collections.Counter:
>>> multilist = [[1,2],[3,4,5],[3,4,5],[5,6],[5,6],[5,6]]
>>> multituples = [tuple(l) for l in multilist]
>>> from collections import Counter
>>> tc = Counter(multituples)
>>> tc
Counter({(5, 6): 3, (3, 4, 5): 2, (1, 2): 1})
To get the set of elements you just need the keys:
>>> tc.keys()
dict_keys([(1, 2), (3, 4, 5), (5, 6)])
If you want to guarantee that the order of the unique items is the same as in the original list, you could do something like:
>>> class Seen(set):
... def __contains__(self, item):
... res = super(Seen, self).__contains__(item)
... self.add(item)
... return res
...
>>> seen = Seen()
>>> [item for item in multilist if tuple(item) not in seen]
[[1, 2], [3, 4, 5], [5, 6]]
>>>
As #ReutSharabani suggested, you can use tuples as dictionary keys, and then convert back to lists for display purposes. The code below doesn't reply on collections (not that there's anything wrong with that).
multilist = [[1,2],[3,4,5],[3,4,5],[5,6],[5,6],[5,6]]
histogram = {}
for x in multilist:
xt = tuple(x)
if xt not in histogram:
histogram[xt] = 1
else:
histogram[xt] += 1
for k,c in histogram.items():
print "%r: count %d times" % (list(k),c)
print [list(x) for x in histogram.keys()]
You can try like this,
>>> multilist = [[1,2],[3,4,5],[3,4,5],[5,6],[5,6],[5,6]]
>>> c = [multilist.count(l) for l in multilist]
>>> for ind, l in enumerate(multilist):
... print( "%s: count %d times" % (str(l), c[ind]))
...
[1, 2]: count 1 times
[3, 4, 5]: count 2 times
[3, 4, 5]: count 2 times
[5, 6]: count 3 times
[5, 6]: count 3 times
[5, 6]: count 3 times
>>> {str(item): multilist.count(item) for item in multilist }
{'[1, 2]': 1, '[3, 4, 5]': 2, '[5, 6]': 3}
How about using repr( alist) to convert it to its text string representation?
from collections import defaultdict
d = defaultdict(int)
for e in multilist: d[ repr(e)] += 1
for k,v in d.items(): print "{0}: count {1} times".format( k,v)
You can use a dictionary for this
count_data = {}
for my_list in multilist:
count_data.setdefault(tuple(my_list), 0)
count_data[tuple(my_list)] += 1

User List to Remove keys from Dictionary

What is the best way to get a user to be able to enter a list(or singular) number to remove a string key entry from a dictionary?
so far this is where I am.
My dictionary to remove the values from(the dictionary is generated so will vary).
d = {'Seven': 22, 'Six': 0, 'Three': 35, 'Two': 0, 'Four': 45, 'Five': 34, 'Eight': 0}
1) So how do I get the input is my first query. This was my attempt but failed.
>>> s = raw_input('1 2 3 4')
1 2 3 4
>>> numbers = map(str, s.split())
>>> numbers
[]
>>> s = raw_input('1 2 3 4')
1 2 3 4
>>> numbers = map(int, s.split())
>>> numbers
[]
2) How would I convert the ints to word form? Here the range is limited there will never be greater than 20 entries per dictionary.
So my initial thought was to create a key of sorts to interpret the info.
e = {'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}
and this works not as expected removing only one entry.
>>> e = {'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}
>>> {k:v for k,v in e.items() if v!=(1 and 3)}
{'Four': 4, 'Two': 2, 'One': 1}
My intention is to remove the values from d and not e. Its also not practical as I don't know how many entries the user will enter so using 'and' statements seems wrong.
First, the parameters of raw_input are just for display. You need to enter it yourself:
>>> s = raw_input("Enter a sequence of number: ")
Enter a sequence of number: 1 2 3 4
>>> print s
1 2 3 4
Now, you can just use a list to map it:
m = ['1':'One', '2':'Two', '3':'Three', .., '10':'Ten']
Edit Here is how to convert it:
e = [v for k, v in m.items() if k in s]
Third, dictionary comprehensions (or 'comprehensions' in general) weren't meant to modify an existing object, but to create a new one. The closest you can get is to make it act like a filter, and reassign the results back to d
d = {k:v for k, v in d.items() if k not in e}

Python Sorted by Index

Lets say there is a dictionary
foo = {'b': 1, 'c':2, 'a':3 }
I want to iterate over this dictionary in the order of the appearance of items in the dictionary.
for k,v in foo.items():
print k, v
prints
a 3
c 2
b 1
If we use sorted() function:
for k,v in sorted(foo.items()):
print k, v
prints
a 3
b 1
c 2
But i need them in the order in which they appear in the dictionary i;e
b 1
c 2
a 3
How do i achieve this ?
Dictionaries have no order. If you want to do that, you need to find some method of sorting in your original list. Or, save the keys in a list in the order they are saved and then access the dictionary using those as keys.
From The Python Docs
It is best to think of a dictionary as an unordered set of key: value
pairs, with the requirement that the keys are unique (within one
dictionary).
Example -
>>> testList = ['a', 'c', 'b']
>>> testDict = {'a' : 1, 'c' : 2, 'b' : 3}
>>> for elem in testList:
print elem, testDict[elem]
a 1
c 2
b 3
Or better yet, use an OrderedDict -
>>> from collections import OrderedDict
>>> testDict = OrderedDict([('a', 1), ('c', 2), ('b', 3)])
>>> for key, value in testDict.items():
print key, value
a 1
c 2
b 3
Maybe this?
sorted(foo, key=foo.get)
If you want to use your OrderedDict multiple times, use an OrderedDict like people have said. :) If you just want a one-liner for a one-off, change your sort function:
sorted(foo.items(), lambda a,b:a[1]-b[1])
You can do this by one-liner:
>>> sorted(foo.items(), key=lambda x: x[1])
[('b', 1), ('c', 2), ('a', 3)]
An ordered dictionary would have to be used to remember the order that they were stored in
>>>from collections import OrderedDict
>>>od = OrderedDict()
>>>od['b'] = 1
>>>od['c'] = 2
>>>od['a'] = 3
>>>print od
OrderedDict([('b',1), ('c',2), ('a',3)]
The see this more directly, the order you used to create the dict is not the order of the dict. The order is indeterminate.
>>> {'b': 1, 'c':2, 'a':3 }
{'a': 3, 'c': 2, 'b': 1}
If you just want to sort them by the keys do:
sorted_by_keys_dict = dict((y,x) for x,y in foo.iteritems())
for k,v in sorted(sorted_by_keys_dict.items()):
print v, k
a 1
c 2
b 3
or simply:
for k,v in sorted(dict((y,x) for x,y in foo.iteritems()).items()):
print v, k
a 1
c 2
b 3

Categories