Convert array to a dictionary of counts?

Is there a built-in function that converts an array of strings into a dictionary, where each key is a unique element in the array, and each value is the number of times that the corresponding key appeared in the array? I wrote such a function (below), but I would prefer to use either a built-in function, or at least a function from a common library.

def setToMap(array):
    dict = {}
    for element in array:
        if element in dict:
            dict[element] += 1
        else:
            dict[element] = 1
    return dict


Thanks!
BerkeleyJeffAsked:
Who is Participating?
 
RichieHindleConnect With a Mentor Commented:
For what it's worth, here's how I'd spell it:

def count_items(seq):
    counts = {}
    for s in seq:
        counts[s] = counts.get(s, 0) + 1
    return counts

if __name__ == '__main__':
    TEST = ['red', 'green', 'blue', 'green', 'pink', 'red', 'green']
    print count_items(TEST)

And also for what it's worth, one of the reasons Python is more elegant than Perl is that you can't express four line's worth of code in one line.  8-)
0
 
RichieHindleCommented:
No, I don't believe there's a built-in function to do this.

Most people build up their own module of such functions, and import that module into each of their projects.
0
 
peprCommented:
In fact, you are implementing the multi-set (or bag). Using the dictionary type, which is very efficient in Python, is fine for that. Even the Sets module--the predecessor of built-in set type--implemented the sets  using the dictionary type. The comment says "This module implements sets using dictionaries whose values are ignored."

I personally would call the function bagFromSeq(seq), because you can iterate through any sequence of whatever the same way. I would also not use the identifier dict for the dictionary, because you are masking the same name of a built-in type.

You can even think about building your class Bag(dict):  if it makes sense in your case. Otherwise, you code looks fine.
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
BerkeleyJeffAuthor Commented:
Thanks for the suggestions. In response, I've rewritten the code and moved it to a seperate module:

def accumulate(hash, key, value):
    if key in hash:
        hash[key] += value
    else:
        hash[key] = value

def multisetCounts( multiset ):
    counts = {}
    for element in multiset:
        accumulate(counts, element, 1)
    return counts


Is there anything further that could be improved? I'm pretty new to Python, coming from Perl. Btw/in Perl this type of routine could be written in one short line:

map {counts{$_}++} multiset;
 

I'm surprised Python (a successor to Perl, known for its elegance) would require 5x as much code.
0
 
ramromConnect With a Mentor consultant Commented:
counts={}
map(lambda x:counts.update({x:counts.get(x,0)+1}),seq)
0
 
BerkeleyJeffAuthor Commented:
Thanks! It was the 'get' function that I was looking for.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.