在Python中保留来自两个JSON对象的重复条目

时间:2019-01-05 00:08:09

标签: python json amazon-web-services lambda

我在Lambda函数(python)中有两个JSON对象。我想将对象2中的键与对象1中的键进行比较,并删除对象1中不包含的所有条目。

每个对象中都有几百个项目,因此嵌套的for循环将花费太长时间和超时。我发现了diffpy,但这需要将模块导入到我的lambda中,并且我希望有一个本机python解决方案(以最小化我的lambda函数的大小)。

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}]

在上面的示例中,预期的newObject应该仅具有来自第一个对象的名称键/值和来自两个对象的价格键/值。来自对象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 :(得分:0)

除非您修改对象的结构,否则所显示的代码可能已获得“优化”的效果,由于您使用的是字典列表,因此无法删除将迭代通过的嵌套循环每个列表中找到正确的字典。

请考虑将名称用作object1object2(即{'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}]

答案 1 :(得分:-1)

嗯,正如评论中已经建议的那样,问题有点不完整,因为如果两个名称相同但价格不同的集合中都存在相同的名称,我们将不知道要做什么。

正如注释中所述,您可以使用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))]

这应该起作用,前提是假定lambda的第一个参数优先。您可以将“ x for o1中的x”更改为“ x o2中x的x”以使第二个版本优先。

如果您要排除价格不同但名称相同的商品,事情会变得更加复杂。我不知道您的用例是什么,也不知道为什么按原样构造对象,但是这样做可能会更容易:

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]]

显然,这不是lambda或单行代码,但是它稍微灵活一些(例如,除去if部分以使object1优先,而不是排除冲突值)。