Сравнение скорости решений, представленных до сих пор:
def f1(words):
c = Counter()
for word in words:
c.update(set(word.lower()))
return c
def f2(words):
return Counter(
c
for word in words
for c in set(word.lower()))
def f3(words):
d = {}
for word in words:
for i in set(word.lower()):
d[i] = d.get(i, 0) + 1
return d
Моя функция синхронизации (используя разные размеры для списка слов):
word_list = [
'tree', 'bone', 'indigo', 'developer', 'python',
'language', 'timeit', 'xerox', 'printer', 'offset',
]
for exp in range(5):
words = word_list * 10**exp
result_list = []
for i in range(1, 4):
t = timeit.timeit(
'f(words)',
'from __main__ import words, f{} as f'.format(i),
number=100)
result_list.append((i, t))
print('{:10,d} words | {}'.format(
len(words),
' | '.join(
'f{} {:8.4f} sec'.format(i, t) for i, t in result_list)))
Результаты:
10 words | f1 0.0028 sec | f2 0.0012 sec | f3 0.0011 sec
100 words | f1 0.0245 sec | f2 0.0082 sec | f3 0.0113 sec
1,000 words | f1 0.2450 sec | f2 0.0812 sec | f3 0.1134 sec
10,000 words | f1 2.4601 sec | f2 0.8113 sec | f3 1.1335 sec
100,000 words | f1 24.4195 sec | f2 8.1828 sec | f3 11.2167 sec
Counter
со списком (здесь как f2()
), кажется, самый быстрый. Использование counter.update()
кажется медленной точкой (здесь как f1()
).
Насколько я знаю, пока нет хорошего представления. Я узнал их, переписав код Олега. Так что это, безусловно, будет один путь: реализовать слой ввода-вывода на основе левой складки.
Хорошая статья об Итератах была недавно опубликована в Monad Reader:
http://themonadreader.wordpress.com/2010/05/12/issue-16
Эта статья имеет множество примеров и альтернативных реализаций, которые усложняются по мере развития.
У меня есть несколько слайдов по моноидальному синтаксическому анализу, которые создают Parsec на основе Iteratee в качестве промежуточного результата, который может оказаться полезным.
Для пакета перечислителя (который включает итератора) есть пример того, как ИСПОЛЬЗОВАТЬ реализацию, вместо того, чтобы показать, как вы можете переопределить пакет. Он показывает альтернативную реализацию команды unix find, как объяснено в Real World Haskell book (раздел 9).
http://www.mew.org/~kazu/proj/enumerator/
Вероятно, вы также можете использовать его как отправную точку для использования других реализаций.