Использование понимания словаря для создания словаря из списка словарей

Это мой исходный код, он работает так, как мне нужно:

import collections
import json
import yaml

file_list = [
  {'path': '/path/to/file1', 'size': 100, 'time': '2022-02-15'},
  {'path': '/path/to/file2', 'size': 200, 'time': '2022-02-13'},
  {'path': '/path/to/file3', 'size': 300, 'time': '2022-02-12'},
  {'path': '/path/to/file4', 'size': 200, 'time': '2022-02-11'},
  {'path': '/path/to/file5', 'size': 100, 'time': '2022-02-1-'}]

new_dict = collections.defaultdict(list)

for file in file_list:
    new_dict[file['size']].append(file['path'])

print(json.dumps(new_dict, indent=4, sort_keys=True))

Я обнаружил, что использование collections.defaultdict(list) помогает упростить код цикла, поэтому мне не нужно проверять, существует ли уже ключ перед добавлением в его список.

Обновлено:

Можно ли сделать этот код кратким, используя понимание словаря для создания new_dict? Коллекция collections.defaultdict(list) ловит меня.

Что значит "лучше"?

Woodford 16.02.2023 23:35

Если ваш код работает без ошибок и дает правильный результат, вы получите лучшую обратную связь о производительности, стиле и технике, если разместите свой вопрос на Code Review StackExchange.

Woodford 16.02.2023 23:35

«Можно ли сделать этот код лучше, используя понимание словаря для создания new_dict»: Нет. Понимание словаря/списка предназначено для случаев, когда каждая итерация цикла добавляет элемент в словарь, который вы создаете, т.е. если вы сделали new_dict[key] = value в петля. В этом случае вы добавляете к (возможно) уже существующему значению, поэтому вы не можете преобразовать его в понимание dict.

Pranav Hosangadi 16.02.2023 23:40

Код, который использует понимание, не обязательно «лучше», чем код, который этого не делает.

Pranav Hosangadi 16.02.2023 23:40

Если defaultdict вызывает у вас недоумение, измените его на обычный словарь и убедитесь, что каждый new_dict[key] существует и является списком, прежде чем пытаться добавить к нему

Pranav Hosangadi 16.02.2023 23:42

Вопрос только в том, могу ли я использовать понимание словаря для создания нового словаря в одной строке.

quantum231 16.02.2023 23:44
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
Тонкая настройка GPT-3 с помощью Anaconda
Тонкая настройка GPT-3 с помощью Anaconda
Зарегистрируйте аккаунт Open ai, а затем получите ключ API ниже.
0
6
61
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если по какой-то причине вы хотите избежать импорта defaultdict, это один из способов сделать это:

import json

file_list = [
    {'path': '/path/to/file1', 'size': 100, 'time': '2022-02-15'},
    {'path': '/path/to/file2', 'size': 200, 'time': '2022-02-13'},
    {'path': '/path/to/file3', 'size': 300, 'time': '2022-02-12'},
    {'path': '/path/to/file4', 'size': 200, 'time': '2022-02-11'},
    {'path': '/path/to/file5', 'size': 100, 'time': '2022-02-1-'}]

new_dict = {}

for file in file_list:
    new_dict[file['size']] = (files := new_dict.get(file['size'], []))
    files.append(file['path'])

print(json.dumps(new_dict, indent=4, sort_keys=True))

И если вам не нравится постоянное переназначение этого списка на запись в словаре (мне не очень):

for file in file_list:
    if file['size'] not in new_dict:
        new_dict[file['size']] = []
    new_dict[file['size']].append(file['path'])

(Обратите внимание, что глубина отступа по умолчанию для Python равна 4, вы сделаете другим и себе в будущем одолжение, приняв это раньше, чем позже)

Как указано в комментариях, возможно, более элегантное решение:

for file in file_list:
    new_dict.setdefault(file['size'], []).append(file['path'])

Однако, несмотря на то, что можно придумать однострочное понимание, оно не будет более эффективным, быстрым или удобочитаемым. На самом деле, скорее всего, ни один из них - так какой в ​​этом смысл?

Более короткий код часто является лучшим кодом, если он не ставит под угрозу функциональность или удобочитаемость, но никогда не должен быть целью сам по себе.

Например, рассмотрим этот (плохой) пример:

c_dict = {size: [fp['path'] for fp in file_list if fp['size'] == size] for size in set(fs['size'] for fs in file_list)}

И хотя это одна строка, вы, вероятно, захотите написать ее так для удобочитаемости, и в этот момент у вас просто будет больше кода, чем раньше:

c_dict = {
    size: [fp['path'] for fp in file_list if fp['size'] == size] 
    for size in set(fs['size'] for fs in file_list)
}

Вопрос только в том, могу ли я использовать понимание словаря для создания нового словаря в одной строке.

quantum231 16.02.2023 23:44
files = new_dict.setdefault(file['size'], []) — менее неуклюжий способ написания строки с помощью оператора «морж».
Pranav Hosangadi 16.02.2023 23:46

Внутри цикла for на самом деле может быть одна строка: new_dict.setdefault(file['size'], list()).append(file['path'])

nigh_anxiety 16.02.2023 23:48

@ quantum231 Нет, это нельзя решить с помощью понимания словаря для этого сценария, но вы можете избежать использования defaultdict, используя методы get() или setdefault() в обычном словаре.

nigh_anxiety 16.02.2023 23:51

Почему мы не можем сделать что-то вроде этого: new_dict = {k: v для файла в списке_файлов: setdefault(file['size'], []).append(file['path'])} Я относительно новичок в Python и время от времени пишу сценарии, чтобы облегчить себе работу.

quantum231 16.02.2023 23:51

Я не думаю, что есть смысл подробно объяснять, почему то, что вы предложили, не сработает (по разным причинам), но см. Ответ для примера понимания, выполняющего эту работу. Однако, если бы я вел курс Python, вы бы получили меньше баллов за этот ответ, чем за любой другой, поскольку он ни в чем не лучше.

Grismar 16.02.2023 23:55

Потому что это недопустимый синтаксис Python. setdefault() и get() — это методы dict, поэтому их нужно вызывать в экземпляре dict. Вы можете написать функцию генератора, которую вы могли бы перебирать, чтобы получить следующий размер файла и путь из списка файлов, и использовать это в своем понимании dict, но тогда вы на самом деле пишете больше кода.

nigh_anxiety 16.02.2023 23:55

@quantum «почему мы не можем сделать ...»: см. Мой комментарий к вашему вопросу выше, но хороший учебник по пониманию, вероятно, поможет вам лучше. Понимание используется, когда каждая итерация вашего цикла предоставляет одно значение (или пару ключ-значение) для построения списка или словаря.

Pranav Hosangadi 16.02.2023 23:58

Хорошо, я понимаю, что мое понимание было неполным

quantum231 17.02.2023 00:04
Ответ принят как подходящий

Не могу утверждать, что это более «кратко», но в конце концов это понимание слова: D

from itertools import groupby
from operator import itemgetter
sort_list = sorted(file_list, key=itemgetter('size'))
groups = groupby(sort_list, key=itemgetter('size'))
print({k:[i['path'] for i in g] for k, g in groups})

Просто убедитесь, что ваши данные связны.

file_list = [
    {'path': '/path/to/file1', 'size': 100, 'time': '2022-02-15'},
    {'path': '/path/to/file2', 'size': 200, 'time': '2022-02-13'},
    {'path': '/path/to/file3', 'size': 300, 'time': '2022-02-12'},
    {'path': '/path/to/file4', 'size': 200, 'time': '2022-02-11'},
    {'path': '/path/to/file5', 'size': 100, 'time': '2022-02-1-'}]

new_dict = {key:  [file_dict[key] for file_dict in file_list] for key in file_list[0].keys()}

Для краткости просто используйте DataFrame???

new_dict = pd.DataFrame(file_list).to_dict(orient='list')

Никогда раньше не сталкивался с фреймворком данных

quantum231 17.02.2023 00:04

Другие вопросы по теме