Python: Список dict, если существует инкремент значение dict, если не добавляют новый dict

Или, провальный дурак:

gzip -c mysqldbbackup.sql | uuencode mysqldbbackup.sql.gz  | mail -s "MySQL DB" backup@email.com
91
задан Natim 12 February 2019 в 15:38
поделиться

4 ответа

Это очень странный способ организовать вещи. Если вы сохранили в словаре, это легко:

# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
    if not url in urls_d:
        urls_d[url] = 1
    else:
        urls_d[url] += 1

Этот код для обновления словаря счетчиков является обычным «шаблоном» в Python. Это настолько распространено, что существует специальная структура данных, defaultdict , созданная, чтобы сделать это еще проще:

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

Если вы обращаетесь к defaultdict с помощью ключа, а ключ еще нет в defaultdict , ключ автоматически добавляется со значением по умолчанию. defaultdict принимает переданный вами вызываемый объект и вызывает его для получения значения по умолчанию. В этом случае мы передали класс int ; когда Python вызывает int () , он возвращает нулевое значение. Итак, при первой ссылке на URL-адрес его счетчик инициализируется нулевым значением, а затем вы добавляете к нему единицу.

Но словарь, полный счетчиков, также является распространенным шаблоном, поэтому Python предоставляет готовый к использованию класс: контейнеры.Counter Вы просто создаете экземпляр Counter , вызывая метод класс, передаваемый в любой итерируемый объект; он создает словарь, в котором ключи являются значениями из итерируемого объекта, а значения - это количество раз, когда ключ появлялся в итерируемом объекте. Приведенный выше пример принимает следующий вид:

from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)

Если вам действительно нужно сделать так, как вы показали, самым простым и быстрым способом было бы использовать любой из этих трех примеров, а затем построить тот, который вам нужен.

from collections import defaultdict  # available in Python 2.5 and newer

urls_d = defaultdict(int)
for url in list_of_urls:
    urls_d[url] += 1

urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]

Если вы используете Python 2.7 или новее, вы можете сделать это однострочным:

from collections import Counter

urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]
181
ответ дан 24 November 2019 в 06:35
поделиться

Использование значения по умолчанию работает, но также работает:

urls[url] = urls.get(url, 0) + 1

используя .get , вы можете получить возврат по умолчанию, если он не существует. По умолчанию это None, но в случае, если я вам послал, это будет 0.

131
ответ дан 24 November 2019 в 06:35
поделиться

Используйте defaultdict :

from collections import defaultdict

urls = defaultdict(int)

for url in list_of_urls:
    urls[url] += 1
22
ответ дан 24 November 2019 в 06:35
поделиться

Чтобы сделать именно по-вашему? Вы можете использовать структуру for ... else

for url in list_of_urls:
    for url_dict in urls:
        if url_dict['url'] == url:
            url_dict['nbr'] += 1
            break
    else:
        urls.append(dict(url=url, nbr=1))

, но она довольно неэлегантна. Вам действительно нужно хранить посещенные URL-адреса в виде СПИСКА? Если вы отсортируете его как dict, например, проиндексированный строкой url, он будет намного чище:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}

for url in list_of_urls:
    if url in urls:
        urls[url]['nbr'] += 1
    else:
        urls[url] = dict(url=url, nbr=1)

Несколько вещей, которые следует отметить во втором примере:

  • посмотрите, как использовать dict для url ] устраняет необходимость просматривать весь список URL при тестировании для одного единственного URL . Этот подход будет быстрее.
  • Использование dict () вместо фигурных скобок делает ваш код короче
  • с использованием list_of_urls , url и url в качестве имен переменных затрудняют анализ кода. Лучше найти что-нибудь более понятное, например urls_to_visit , urls_already_visited и current_url . Я знаю, это дольше. Но это яснее.

И, конечно, я предполагаю, что dict (url = 'http: //www.google.fr', nbr = 1) - это упрощение вашей собственной структуры данных, потому что в противном случае url могли бы быть просто:

urls = {'http://www.google.fr':1}

for url in list_of_urls:
    if url in urls:
        urls[url] += 1
    else:
        urls[url] = 1

Что может быть очень элегантно с помощью defaultdict stance:

urls = collections.defaultdict(int)
for url in list_of_urls:
    urls[url] += 1
3
ответ дан 24 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: