1

Task: The first line contains the integer, N. The next N lines each contain a word. Output should be: 1) On the first line, output the number of distinct words from the input. 2) On the second line, output the number of occurrences for each distinct word according to their appearance in the input. I had no difficulty with #1. For point #2, I used Counter to get the occurrences of the words. However I am having difficulty in printing them in the order which it was received. Below is my code.

from collections import Counter
from collections import OrderedDict
all_words=[]
for _ in range(int(raw_input())):
    name=raw_input()
    all_words.append(name)
uniqlst=list(set(all_words)) 
print len(uniqlst)##On the first line, output the number of distinct words from the input. 


x=OrderedDict(Counter(all_words)) #This is where I am having trouble to get values of x in the order it was received.
print " ".join(map(str,x.values()))

Input:

4
bcdef
abcdef
bcde
bcdef

Output of my code:

3
1 1 2

Expected output:

3
2 1 1
Sel_Python
  • 191
  • 2
  • 7
  • 16
  • reverse the list before mapping and joining. – Nouman Sep 04 '18 at 20:25
  • 1
    The `Counter` gives you values in arbitrary order. The `OrderedDict` then preserves that arbitrary ordering. That isn't very helpful. What you need to do is create an `OrderedCounter`, which is [a trivial example in the `collections` docs](https://docs.python.org/3/library/collections.html?highlight=counter#ordereddict-examples-and-recipes). – abarnert Sep 04 '18 at 20:25
  • @Bazingaa I am not using set to get value of x. – Sel_Python Sep 04 '18 at 20:26

1 Answers1

0

This isn't going to work:

x=OrderedDict(Counter(all_words))

First you're creating a Counter by iterating all_words. Since a Counter is just a dict under the hood, depending on your Python version, this may be in insertion order, consistent-but-arbitrary order, or explicitly-randomized order.

Then you create an OrderedDict by iterating that Counter. That will preserve the order of the Counter—which isn't very useful if the Counter was in arbitrary order.

What you want to do is to create a class that does everything Counter does but also does everything OrderedDict does. Which is trivial:

class OrderedCounter(Counter, OrderedDict):
    'Counter that remembers the order elements are first encountered'

This isn't quite perfect, because its repr will give you the wrong class name, and it won't pickle right. But fixing that is almost as simple. In fact, it's given as an example in the docs:

class OrderedCounter(Counter, OrderedDict):
    'Counter that remembers the order elements are first encountered'

    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

    def __reduce__(self):
        return self.__class__, (OrderedDict(self),)
user2357112
  • 260,549
  • 28
  • 431
  • 505
abarnert
  • 354,177
  • 51
  • 601
  • 671