4

I have a list

L = Counter(mywords)

Where

mywords = ['Well', 'Jim', 'opportunity', 'I', 'Governor', 'University', 'Denver', 'hospitality', 'There', 'lot', 'points', 'I', 'make', 'tonight', 'important', '20', 'years', 'ago', 'I', 'luckiest', 'man', 'earth', 'Michelle', 'agreed', 'marry', '(Laughter)', 'And', 'I', 'Sweetie', 'happy'] 

It's much longer than that but that's a snippet.

Now what I do next is:

print ("\n".join(c.most_common(10)))

Because I want it to show the 10 most commonly used words in that list AND their counts, but I want it to print out into new lines for each item in the list, instead I get this error:

TypeError: sequence item 0: expected str instance, tuple found

Any help would be appreciated, using Python 3.

Goose
  • 2,130
  • 10
  • 32
  • 43

4 Answers4

5
print ("\n".join(map(str, c.most_common(10))))

If you want more control over the format, you can use a format string like this

print ("\n".join("{}: {}".format(k,v) for k,v in c.most_common(10)))
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • No. This will print `('I', 4)\n('man', 1)\n`, which is almost certainly not what he actually wants. – abarnert Oct 23 '12 at 00:42
  • Actually, I tested it out and it works just fine. Can you explain what the map function does exactly? I'm very new to Python. – Goose Oct 23 '12 at 00:46
  • More general than what? "I want it to show the 10 most commonly used words in that list." Printing out (word, count) pairs for the words isn't a more general answer, it's the answer to a different problem. – abarnert Oct 23 '12 at 00:53
  • Also, you really ought to be teaching new Python users compehensions, not map. See http://stackoverflow.com/questions/1247486/python-list-comprehension-vs-map for a long discussion, but the short version is: how do you change the `map` call to return `x[0]` instead of `str(x)`? – abarnert Oct 23 '12 at 00:56
  • @abarnert, `map(itemgetter(0), c.most_common(10))` – John La Rooy Oct 23 '12 at 01:55
  • The point is that you can't just write the expression you want, you have to find (or write) an equivalent function. `x[0]` is much more readable than `itemgetter(0)(x)`. I don't want to get into this any farther; Guido has made the argument more eloquently than I ever could (although he couldn't convince the rest of python-dev to drop `map` and `filter` completely). – abarnert Oct 24 '12 at 19:45
1

The simplest is:

for item, freq in L.most_common(10):
    print(item, 'has a count of', freq) # or
    print('there are {} occurrences of "{}"'.format(freq, item))
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • This is correct, but it's not simplest. The simplest is to fix the existing generator expression he almost had right. – abarnert Oct 23 '12 at 00:45
  • +1: This is the simplest. Just because someone almost wrote a illegible line of code that works doesn't mean that fixing it is simplest. To the contrary, that illegible line of code isn't maintainable and therefore should be jettisoned and rewritten in a maintainable form (IE, the one Jon has offered.) – ArtOfWarfare Jul 25 '13 at 12:42
1

If you just want the strings:

print("\n".join(element for element, count in c.most_common(10)))

If you want the strings and the counts printed in the form ('foo', 11):

print ("\n".join(str(element_and_count) 
       for element_and_count in c.most_common(10)))

If you want the strings and counts in some other format of your choice:

print ("\n".join("{}: {}".format(element, count) 
       for element, count in c.most_common(10)))

Why? The most_common function returns (element, count) pairs. Those things are tuples, not strings. You can't just join tuples together. You can, of course, convert it to a string (option #2 above), but that only works if you actually want the format ('foo', 11) for each line. To get the other two options, you want to ignore half the tuple and use the other, or write your own format expression.

In any case, you want to do something to each member of the sequence returned by most_common. The Pythonic way to do that is with a list comprehension or generator expression.

Meanwhile, you should learn how to debug these kinds of cases. When join gives you a TypeError, break it up into pieces until you find the one that stores working (and try it with 2 instead of 10, just so there's less to read):

>>> print("\n".join(c.most_common(2)))
TypeError: sequence item 0: expected str instance, tuple found
>>> c.most_common(2)
[('I', 4), ('man', 1)]

Aha! Each thing in the list is a tuple of two things, not just a string. Why?

>>> help(c.most_common)
most_common(self, n=None) method of collections.Counter instance
    List the n most common elements and their counts from the most
    common to the least.  If n is None, then list all element counts.

    >>> Counter('abcdeabcdabcaba').most_common(3)
    [('a', 5), ('b', 4), ('c', 3)]

OK, so it returns the most common elements and their counts. I just want the elements. So:

>>> [element for element, count in c.most_common(2)]
['I', 'man']

Now that's something I can join:

>>> '\n'.join([element for element, count in c.most_common(2)])
'I\nman'

And I don't need both brackets and parents (I can just use an expression instead of a list comprehension):

>>> '\n'.join(element for element, count in c.most_common(2))
'I\nman'

And now, I can print it:

>>> print('\n'.join(element for element, count in c.most_common(2)))
I
man

And now that it's working, print all 10:

>>> print('\n'.join(element for element, count in c.most_common(10)))
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Thanks for explaining it all out, I should've been more clear in the original question, I DO want the counts as well, not just the words. If you can edit your answer I will accept it, thanks. – Goose Oct 23 '12 at 01:42
  • I've edited my answer. But in that case, the second version of gnibbler's answer (which is, other than variable naming, identical to the third version of mine) already gave you what you want. – abarnert Oct 24 '12 at 19:46
1

I'm surprised that nobody suggested using the unpacking operator *, since you say python3 so why not do the following, you can test it here too.

print(*[x[0]for x in L.most_common(10)], sep="\n")

Related questions

Community
  • 1
  • 1
Juan Cortés
  • 20,634
  • 8
  • 68
  • 91