Сохраняйте повторяющиеся записи из двух объектов JSON в Python - PullRequest
0 голосов
/ 05 января 2019

У меня есть два объекта JSON в функции Lambda (python). Я хочу сравнить ключи от объекта 2 с ключами в объекте 1 и удалить все записи, которые не содержатся в объекте 1.

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

object1 = [{'name': 'apple', 'price': 100}, {'name': 'grape', 'price': 
150}, {'name': 'orange', 'price': 40}]

object2 = [{'name': 'apple', 'price': 200}, {'name': 'grape', 'price': 
350}, {'name': 'orange', 'price': 40}, {'name': 'mango', 'price': 400}]

В приведенном выше примере ожидаемый новый объект должен иметь только ключ / значение имени из первого объекта и ключ / значения цены из обоих объектов. Манго из объекта 2 не содержится в объекте 1, поэтому мы можем игнорировать.

newObject = [{'name': 'apple', 'priceA': 100, 'priceB': 200}, {'name': 
'grape', 'priceA': 150, 'priceB': 350}, {'name': 'orange', 'priceA': 40, 
'priceB': 40}]

Я попытался использовать следующий код для реализации:

newHash= {}
newObject = []
for item in object1:
    name = item["name"]
    priceA = item["price"]
    for item in object2:
        if name == item["name"]:
            newHash["name"] = item["name"]
            newHash["priceA"] = priceA
            newHash["priceB"] = item["price"]
            newObject.append(newHash)

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Если вы не измените структуру своих объектов, код, который вы показали, будет настолько «оптимизирован», насколько вы, вероятно, можете его получить, поскольку из-за того, что вы используете список словарей, невозможно удалить вложенные циклы, которые будут повторяться каждый список, чтобы найти правильный словарь.

Попробуйте использовать имена в качестве ключей в object1 и object2, т.е. {'apple': 100, 'grape': 150}. Таким образом, у вас будет прямой доступ для поиска общих ключей. Структура вывода может оставаться по вашему желанию.

object1 = {'apple': 100,
           'grape': 150,
           'orange': 40}

object2 = {'apple': 200,
           'grape': 350,
           'orange': 40,
           'mango': 400}

common_keys = object1.keys() & object2.keys()

output = [{'name': key, 'priceA': object1[key], 'priceB': object2[key]}
          for key in common_keys]
print(output)
#  [{'name': 'apple', 'priceA': 100, 'priceB': 200},
#   {'name': 'grape', 'priceA': 150, 'priceB': 350},
#   {'name': 'orange', 'priceA': 40, 'priceB': 40}]
0 голосов
/ 05 января 2019

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

Как также отмечено в комментариях, вы можете использовать объект set и его метод .intersection (), чтобы получить то, что вы хотите.

lambda o1,o2: [x for x in o1 if x['name'] in set(y['name'] for y in o1). intersection (set(z['name'] for z in o2))]

Это должно сработать при условии, что первый аргумент лямбды имеет приоритет. Вы можете изменить «x для x в o1» на «x для x в o2», чтобы вторая версия имела приоритет.

Если вы хотите исключить вещи с разными ценами, но с одинаковым названием, все становится немного сложнее. Я не знаю, каков ваш вариант использования или почему объекты структурированы так, как они есть, но может быть проще, если вы сделаете это:

po1={x['name']:x['price'] for x in object1}
po2={x['name']:x['price'] for x in object2}
[{'name':x,'price':po1[x]} for x in set(po1).intersection (set(po2)) if po1[x]==po2[x]]

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

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