Какой эффективный способ сократить и объединить список (list (dict ())), где некоторые словари могут иметь одинаковые ключи, но разные значения - PullRequest
0 голосов
/ 22 апреля 2020

Контекст: у меня есть список идентификаторов организации, где каждый идентификатор организации имеет несколько идентификаторов учетных записей и пар электронной почты. Каждое письмо связано с одним идентификатором учетной записи на организацию (идентификатор организации) (уникальный). Не все электронные письма находятся в каждой из организаций, но некоторые электронные письма находятся в нескольких организациях или даже во всех них. Например, если существует 5 организаций, у каждой организации есть неизвестное количество идентификаторов учетных записей, пар электронной почты. Идентификаторы учетных записей уникальны независимо от организации, с которой они связаны, но в нескольких организациях, связанных с разными идентификаторами учетных записей, есть несколько электронных писем.

Мои данные имеют следующую структуру, и я пытаюсь сделать это в python:

# Note: Each AccountID Value is unique across the board
# Note: Emails are unique per organization, but can be in multiple organizations.
[
    [
        # The value for OrganizationID is the same throughout the list of dictionaries.
        {
            "some-email A": "AccountID",
            "OrganizationID": "Organization A"  # <- The ID is just a string of numbers.
        },
        {
            "some-email B": "AccountID",
            "OrganizationID": "Organization A"
        },
        {
            "some-email C": "AccountID",
            "OrganizationID": "Organization A"
        },
        ...
    ],
    ...
    [
        {
            "some-email C": "AccountID",   #. <- Also in organization A but different Account ID
            "OrganizationID": "Organization LK"
        },
        {
            "some-email K": "AccountID",
            "OrganizationID": "Organization LK"
        },
        ...
    ],
    ...
]

Заказ не имеет значения! Моя последняя цель - превратить это в следующую новую структуру данных.

# Note: Reference is just a list of strings where each string is 
# a concatenation of the "OrganizationID:AccountID" of the respective email.
[
    {
        "Email": "some-email A",
        "Reference": [
            "[Organization A]:[Account ID of "some-email A" in Organization A if exists]",
            ...
            "[Organization X]:[Account ID of "some-email A" in Organization X if exists]",
            ...
        ]
    },
    ...
    {
        "Email": "some-email C",
        "Reference": [
            "[Organization A]:[Account ID of "some-email C" in Organization A if exists]",
            ...
            "[Organization LK]:[Account ID of "some-email C" in Organization LK if exists]",
            ...
        ]
    },
]

В моем текущем наборе данных более 1000 организаций, и у каждой организации есть произвольное количество учетных записей. Некоторые организации могут иметь только одну или две учетные записи, но другие имеют более 600 учетных записей. Ни у одной организации нет нулевых учетных записей.

Редактировать: Мое текущее решение заключается в следующем: Но я хотел посмотреть, есть ли более эффективный способ решения этой проблемы.

re = list()
seen = set()
for _p in dt: # <- this is the first data set list(list(dict()))
    for x in _p: # <- Each dictionary in the list(dict())
        em = list(x.keys())[1] # <- some-email key
        if em not in seen:
            seen.add(em)
            re.append({
                "Email": em,
                "Reference": [x["OrganizationID"] + ":" + x[em]]
            })
        else:
            d = next(i for i in re if i['Email'] == em)
            d["Reference"].append(x["OrganizationID"] + ":" + x[em])

1 Ответ

0 голосов
/ 22 апреля 2020

То, что вы делаете, потребует вложенных для циклов из-за структуры данных, но я думаю, что вы получите лучшую производительность, если уберете предложение if em not in seen, потому что для этого потребуется собственная итерация по набору, который не не нужно, и не создание набора в первую очередь уменьшит накладные расходы. Вот мой подход:

dct = {}
for i1 in range(len(emails)):
    for i2 in range(len(emails[i1])):
        email = next(iter(emails[i1][i2].items()))
        org = emails[i1][0]["OrganizationID"]
        if dct.get(email[0]):
            dct[email[0]].append({org: email[1]})
        else:
            dct[email[0]] = [{org: email[1]}]

Он просматривает каждый ключ, пару значений каждой организации, а затем добавляет комбо org + id, если его еще нет в сообщении электронной почты. Это лучше, потому что dct.get () не выполняет итерацию по списку ключей, он проверяет таблицу ha sh на наличие ключа и, если она не существует, возвращает None

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...