Why can't I iterate over a Counter in Python? - python

Why is that when I try to do the below, I get the need more than 1 value to unpack?
for key,value in countstr:
print key,value
for key,value in countstr:
ValueError: need more than 1 value to unpack
However this works just fine:
for key,value in countstr.most_common():
print key,value
I don't understand, aren't countstr and countstr.most_common() equivalent?
EDIT:
Thanks for the below answers, then I guess what I don't understand is: If countstr is a mapping what is countstr.most_common()? -- I'm really new to Python, sorry if I am missing something simple here.

No, they're not. Iterating over a mapping (be it a collections.Counter or a dict or ...) iterates only over the mapping's keys.
And there's another difference: iterating over the keys of a Counter delivers them in no defined order. The order returned by most_common() is defined (sorted in reverse order of value).

No, they aren't equivalent. countstr is a Counter which is a dictionary subclass. Iterating over it yields 1 key at a time. countstr.most_common() is a list which contains 2-tuples (ordered key-value pairs).

A countstr is a Counter which is a subclass for counting hashable objects. It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values.
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']

You can't iterate the counter values/keys directly but you can copy them into a list and iterate the list.
s = ["bcdef", "abcdefg", "bcde", "bcdef"]
import collections
counter=collections.Counter(s)
vals = list(counter.values())
keys = list(counter.keys())
vals[0]
keys[0]
Output:
2
'bcdef'

Related

Remove items from dictionary if the length of the item is 1 or less

Is there a way to remove a key from a dictionary using it's index position (if it has one) instead of using the actual key (to avoid e.g. del d['key'], but use index position instead)?
If there is then don't bother reading the rest of this question as that's what I'm looking for too.
So, as an example for my case, I have the dictionary d which uses lists for the values:
d = {'acd': ['cad'], 'abd': ['bad', 'dab']}
I want to remove each key completely from such dictionary whose value's items have a length of less than 2 (so if there's only 1 item).
So, in this example, I would want to remove the key 'acd' because it's value's list only has 1 item ['cad']. 'abd' has 2 items ['bad', 'dab'], so I don't want to delete it - only if it contains 1 or less item. This dictionary is just an example - I am working with a much bigger version than this and I need it to remove all of the single item value keys.
I wrote this for testing but I'm not sure how to go about removing the keys I want - or determing what they are.
d = {'acd': ['cad'], 'abd': ['bad', 'dab']}
index_pos = 0
for i in d.values():
#Testing and seeing stuff
print("pos:", index_pos)
print(i)
print(len(i))
if len(i) < 2:
del d[???]
#What do I do?
index_pos += 1
I used index_pos because I thought it might be useful but I'm not sure.
I know I can delete an entry from the dictionary using
del d['key']
But how do I avoid using the key and e.g. use the index position instead, or how do I find out what the key is, so I can delete it?
Just use a dictionary comprehension:
d = {'acd': ['cad'], 'abd': ['bad', 'dab']}
res = {k: v for k, v in d.items() if len(v) >= 2}
Yes, you are creating a new dictionary, but this in itself is not usually a problem. Any solution will take O(n) time.
You can iterate a copy of your dictionary while modifying your original one. However, you should find the dictionary comprehension more efficient. Don't, under any circumstances, remove or add keys while you iterate your original dictionary.
If you doesn't want to create new dict here's how you could change your code. Here we iterate over copy of our dict and then delete keys of our original dict if length of its value is less than 2.
d = {'acd': ['cad'], 'abd': ['bad', 'dab']}
for key in d.copy():
if len(d[key]) < 2:
del d[key]
print(d)

Using the key "MYDICT.get" as a means of sorting the Dictionary

What does the following syntax do differently than simply sorting the list without a key? MYDICT is a dictionary
sorted(MYDICT, key = MYDICT.get)
This is a short way of sort dict keys by value. Here is why:
mydict = {"a": 3, "b": 2, "c": 1}
sorted(mydict, key=mydict.get)
Output is:
['c', 'b', 'a']
The reason is that the key= argument to sorted() is expecting a callable function that takes the current list item as the argument and returns the value to use to sort that item with.
In the above case, mydict.get(key) will return the value of key.
When you iterate over a dict, it only iterates over the keys, not the values.
Putting it all together, sorted(mydict) is iterating over and returning a list containing the sorted keys of mydict, but using mydict.get(key), which returns the value of that key, to do the sorting with.

Using set on Dictionary keys

For my program, I wish to cleanly check whether any elements in a list is a key in a dictionary. So far, I can only think to loop through the list and checking.
However, is there any way to simplify this process? Is there any way to use sets? Through sets, one can check whether two lists have common elements.
This should be easy using the builtin any function:
any(item in dct for item in lst)
This is quick, efficient and (IMHO) quite readible. What could be better? :-)
Of course, this doesn't tell you which keys are in the dict. If you need that, then you're best recourse is to use dictionary view objects:
# python2.7
dct.viewkeys() & lst # Returns a set of the overlap
# python3.x
dct.keys() & lst # Same as above, but for py3.x
You can test for an intersection between the dictionary's keys and the list items using dict.keys:
if the_dict.keys() & the_list:
# the_dict has one or more keys found in the_list
Demo:
>>> the_dict = {'a':1, 'b':2, 'c':3}
>>> the_list = ['x', 'b', 'y']
>>> if the_dict.keys() & the_list:
... print('found key in the_list')
...
found key in the_list
>>>
Note that in Python 2.x, the method is called dict.viewkeys.
As far as efficiency goes, you can't be any more efficient than looping through the list. I would also argue that looping through the list is already a simple process.

Iterating over first half a dictionary in python

How to iterate over first half of dictionary in python
This iterates over all values in the dictionary
for key, value in checkbox_dict.iteritems():
print key,value
But I want to iterate over the first half of the dictionary only.
one way is to do it like this
for key, value in dict(checkbox_dict.items()[:11]).iteritems():
print key,value
Is there any better way also ?
If you mean: over half of the items here's a way:
for key, value in checkbox_dict.items()[:int(len(checkbox_dict)/2)]:
pass
… But be aware: the elements in a normal dictionary don't necessarily keep the same iteration order that was used for inserting the elements … unless you use an OrderedDict.
You can use itertools.islice to slice the dict.iteritems iterator, unlike dict.items() with slice this won't create an intermediate list in memory.
>>> from itertools import islice
>>> d = dict.fromkeys('abcdefgh')
>>> for k, v in islice(d.iteritems(), len(d)/2):
print k, v
...
a None
c None
b None
e None
Note that normal dictionaries are unordered, so the items are returned in arbitrary order.

Values in Dictionaries during a loop

When looping in a dictionary, how do I change the value in the loop.
For example:
listt=[1,4,2]
mydict=[a:d, c:b, q:r]
I am trying to make:
for i in listt:
for key in mydict:
mydict[key]=i
but this does not work. What occurs is the ith value ends up being the last one. in my new dictionary, so it is always a:2, c:2, etc. Instead of a:1, b:4, q:2. I need to store the ith value I think and then use that to change the value in the dictionary. Though I am not sure what I am getting at! Any help would be appreciated!
Keys in dicts are not ordered. So you can not control the pairing between items in listt and keys in the dict mydict.
However, the keys in an OrderedDict are ordered:
import collections
listt=[1,4,2]
mydict=collections.OrderedDict([('a','d'), ('c','b'), ('q','r')])
for item, key in zip(listt, mydict):
mydict[key] = item
print(mydict)
yields
OrderedDict([('a', 1), ('c', 4), ('q', 2)])
there are few misunderstandings with dict here:
it seems like you want to 'update' the dictonary with same keys and new values(with values supplied from new list). problem is, a dictonary does not keep stored items in order; a dictionary {a:d, c:b, q:r} does not mean you can iterate through the dictionary in [a, c, q] order.
also, you're using nested for-loops, that is why every value ends up as last vlues of listt.
you can use the collections.OrderedDict to keep things in order. and, instead of nested for-loops, use zip to combine iterators.
so, your code would be :
from collections import OrderedDict
listt = [1, 4, 2]
mydict = OrderedDict([(a, d), (c, b), (q, r)])
mydict = OrderedDict(zip(mydict.keys(), listt))

Categories