Как получить значения объекта Counter в том порядке, в котором он был получен?

Задача: Первая строка содержит целое число N. Каждая из следующих N строк содержит слово. Выходные данные должны быть: 1) В первой строке выведите количество различных слов из ввода. 2) Во второй строке выведите количество вхождений для каждого отдельного слова в соответствии с их появлением на входе. У меня не было проблем с № 1. Для пункта № 2 я использовал Counter, чтобы получить вхождения слов. Однако у меня возникают трудности с их печатью в том порядке, в котором они были получены. Ниже мой код.

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()))

Входные данные:

4
bcdef
abcdef
bcde
bcdef

Вывод моего кода:

3
1 1 2

Ожидаемый результат:

3
2 1 1

1 ответ

Это не сработает:

x=OrderedDict(Counter(all_words))

Сначала вы создаете Counter перебирая all_words, Так как Counter это просто dict под капотом, в зависимости от вашей версии Python, это может быть порядок вставки, согласованный, но произвольный порядок или явно рандомизированный порядок.

Затем вы создаете OrderedDict повторяя это Counter, Это сохранит порядок Counter- что не очень полезно, если Counter был в произвольном порядке.

Что вы хотите сделать, это создать класс, который делает все Counter делает, но и делает все OrderedDict делает. Что тривиально:

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

Это не совсем идеально, потому что его repr даст вам неправильное имя класса, и это не будет правильно мариновать. Но исправить это почти так же просто. На самом деле, это приведено в качестве примера в документации:

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),)
Другие вопросы по тегам