Ломтик словаря, который является результатом коллекций. Счетчик - PullRequest
0 голосов
/ 04 октября 2018

Пока я пытаюсь создать словарь с помощью dict (x), где x - это фрагмент другого словаря, d (y), где y - это набор collection.Counter ().Это одна строка:

lengths=dict(islice(dict(Counter(input())),3))

Исключение, которое я получаю, это

lengths=dict(islice(dict(Counter(input())),3))
ValueError: dictionary update sequence element #0 has length 1; 2 is required

Насколько я понимаю, эта ошибка возникает, когда функция обновления вызывается только с однимзначение (вместо пары ключ-значение).Я знаю, что что-то плохое в вызовах вложенных функций, но не смог найти это.

Как я могу получить часть словарных элементов?Есть ли способ, которым я мог бы сделать это без фактического перебора всего словаря и обновления до нового словаря?

Ответы [ 4 ]

0 голосов
/ 05 октября 2018

(Python 2.6+) Я мог бы решить эту проблему, используя OrderedCounter .Вы можете увидеть объяснение этого здесь: Как работает рецепт Упорядоченного счетчика

from collections import Counter, OrderedDict


class OrderedCounter(Counter, OrderedDict):
    pass

dict([c for c in OrderedCounter(sorted(input())).most_common(3)])

Дальнейшее добавление, most_common (n) - это метод collection.Counter, который возвращает первое nэлементы в этом словаре.Ссылка: most_common([n])

0 голосов
/ 04 октября 2018

Итерация словаря даст только ключи.Чтобы нарезать словарь, вам нужно извлечь ключ и значение через dict.items.Кроме того, примечание collections.Counter является подклассом dict, поэтому преобразование dict не требуется.

Как получить часть словарных элементов?Есть ли способ, которым я мог бы сделать это без фактической итерации по всему словарю и обновления до нового словаря?

Нет, вы не можете нарезать словарь без итерации.Вы можете создать новый объект Counter и использовать islice для возврата первых 3 значений в порядке вставки .Это все еще требует итерации и работает в Python 3.6+, где словари упорядочены по вставке.

from collections import Counter
from itertools import islice

c = Counter('abbcccddeeff')

lengths = Counter()
lengths.update(dict(islice(c.items(), 3)))

print(lengths)

Counter({'c': 3, 'b': 2, 'a': 1})

Несколько замечаний:

  1. Порядок, в котором Counter объектыПечать не соответствует внутреннему порядку, в котором хранятся элементы, который по-прежнему заказ на вставку .См. Также Как упорядочить Counter / defaultdict в Python 3.7?
  2. Вы можете задаться вопросом, почему, если упорядочены словари, как в Python 3.6+, вы не можете нарезать прямо.Существуют структурные причины, по которым это невозможно: см. Эффективный доступ к элементам словаря по позициям в Python 3.6+ .
0 голосов
/ 04 октября 2018

Итак, Исслиц ожидает повторения.Таким образом, чтобы разделить словарь, вы, вероятно, должны преобразовать словарь в список кортежей.Но словарь не поддерживает порядок вставки.Поэтому, чтобы убедиться, что вы, вероятно, можете использовать Ordered dict из коллекций lib в python.

    from collections import Counter, OrderedDict
    from itertools import islice

    data = OrderedDict(list(islice(sorted(Counter("aaabbbccccddddd").items(),key=lambda element: (-element[1], element[0])), 3)))
0 голосов
/ 04 октября 2018

Вы можете использовать islice для элементов объекта Counter (который является подклассом dict, поэтому нет необходимости в преобразовании dict), а затем преобразовать нарезанные элементы в dict с помощью конструктора dict.

Например,

dict(islice(Counter('abbcccddeeff').items(), 3))

возвращает: (обратите внимание на отсутствие d, e и f)

{'a': 1, 'b': 2, 'c': 3}
...