比较两个 JSON 结果并生成新条目的新 JSON (Python)

Posted

技术标签:

【中文标题】比较两个 JSON 结果并生成新条目的新 JSON (Python)【英文标题】:Compare two JSON results and make new JSON of new entries (Python) 【发布时间】:2021-11-29 00:49:42 【问题描述】:

我正在查询一个 API 以尝试在 JSON 中查找新条目,我被困在如何“减去”这两个列表上,以便获得一个新的 JSON 对象,其中只有两个列表之间的新项目。

我现在做的是:

    我正在查询 API。 将 JSON 结果存储到变量中。 等待 30 秒。 再次查询 API。 比较 PreviousJSON == NewJSON 如果有区别,那么:

^^ 这是我卡住的地方,我可以比较值,但我不知道如何只找到新值并迭代它们。

我基本上是在监控这个 API: https://qzlsklfacc.medianetwork.cloud/nft_for_sale?collection=galacticgeckospacegarage

并试图找到新的列表和新出售的物品。

现在要比较现有项目之间的差异,我正在执行以下操作:

# check if new listings are the same as the old listings
    if prevListings != newListings:
        await bot.get_channel(893292122298540083).send("New listings found!")
        for listingOld in prevListings:
           for listingNew in newListings:
               if listingNew['id'] == listingOld['id']:
                   if listingNew['lastSoldPrice'] is not None:
                       if listingNew['lastSoldPrice'] != listingOld['lastSoldPrice']:
                           Do something.

所以这两个问题是:

    有没有更好的方法来比较两个 JSON 对象中的两个相同条目(未排序) 有没有办法获得仅包含 PrevListings 中不存在的新条目的第三个 JSON。

这是 JSON 响应中每个项目的 JSON 结构

0000:
    'id':1155682
    'token_add':'HV4duJjY67DD4doX9ffvzfoaENAAkFuwz9qtbwAweDAG'
    'number':1
    'currency':'SOL'
    'price':29
    'link_img':'https://www.arweave.net/iZs-LiMAg5mIqaqxrd--EtcKhHTNtPZFPrZyIK95nUc?ext=jpeg'
    'for_sale':1
    'programId':'CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz'
    'name':'Galactic Gecko #6376'
    'description':'undefined'
    'escrowAdd':'4TULtxsixV4NLdZWqY45d4Mz5XrE4q4CfTECNcvaZDY1'
    'seller_address':'Er6QJPusC1JsUqevTjFKXtYHbgCtJkyo1DNjEBWevWut'
    'attributes':'Faction: Barada,Body: Light Pink,Armor: Planetary Kirtle,Mouth: Pensive,Helmet: Signal Deflector,Ears: Planetary Muffler,Eyes: Augmented Surveyor'
    'skin':None
    'type':'galacticgeckospacegarage'
    'ranking':None
    'buyerAdd':None
    'blockhash':None
    'lastSoldPrice':13.99

我正在使用 Python 3.8

谢谢!

【问题讨论】:

您应该比较究竟什么。请添加详细说明。 您要比较键(0000)还是值(数据)? 我想比较 Last Sale Price,如果数据不同,则将整个节点(连同所有子节点)添加到仅包含更新数据的新字典中。那,并且还获取新条目(在 JSON B 中但不在 JSON A 中的 ID,并将它们存储在 JSON C 中(新) 【参考方案1】:

试试下面的(data_1data_2代表2次API调用的结果)

data_1 = ['lastSoldPrice':12,'id':14,'lastSoldPrice':18,'id':15,'lastSoldPrice':149,'id':146]
data_2 = ['lastSoldPrice':12,'id':17,'lastSoldPrice':18,'id':15,'lastSoldPrice':142,'id':146,'lastSoldPrice':1422,'id':166]
# convert list to dict
data_1 = entry.get('id'): entry for entry in data_1
data_2 = entry.get('id'): entry for entry in data_2
# set operation to find new and common
new_entries = data_2.keys() - data_1.keys()
print(f'New entry ids: new_entries')
for _id in new_entries:
  print(f'\t data_2.get(_id)')
common_entries = data_2.keys() & (data_1.keys())
print(f'Common entry ids: common_entries')

# loop over common entries and see if there is a price change
for _id in common_entries:
  p1 = data_1.get(_id)['lastSoldPrice']
  p2= data_2.get(_id)['lastSoldPrice']
  if p1 != p2:
    print(f'Price change for id _id. Old price: p1, new price: p2')

输出

New entry ids: 17, 166
     'lastSoldPrice': 12, 'id': 17
     'lastSoldPrice': 1422, 'id': 166
Common entry ids: 146, 15
Price change for id 146. Old price: 149, new price: 142

【讨论】:

这很有帮助,但是如果发现差异时,我想返回整个节点子节点,而不仅仅是 ID,因为我想返回新列表的元数据 只需遍历“新”ID 并执行 data_2.get('the_new_id') - 它会返回整个节点。 (代码已更新【参考方案2】:

您采用的方法取决于***键(例如0000)对于各个对象是否唯一。如果是,您可以使用这些键来过滤返回的对象,如果不是,您需要做更多的工作。

***键是 ID

如果***键对对象是唯一的,您可以简单地迭代新字典并查看其键是否在现有字典中。在下面的代码中,first 是初始字典,second 是我们的第二个响应。输出存储在字典third中。


third =   # empty dictionary for our output.
for key, data in second.items():
    if key not in first:  # is new
        third[key] = data

所以我们遍历second 字典,检查每个键是否在first 字典中。如果 不是,我们将其添加到 third

您也可以使用字典理解来执行此操作(结果相同)。

third = key:value for key, value in second.items() if key not in first

id 在数据中

如果键不是 ID,那么您就会遇到问题:您需要通过嵌套在第一个字典中的内容来过滤第二个字典。我们可以为second 中的每个条目迭代first 字典,但这很慢。

因为我们只想知道如果它在里面,我们可以将我们需要检查的值(例如id)提取到一个新变量中。一个集合对此很有用,因为查找速度很快。

# build a set of values from the first dictionary.
first_ids = set(o['id'] for o in first.values())

third = 
for key, data in second.items():
    if data['id'] not in first_ids:
        third[key] = data

或者,再次使用字典理解

first_ids = set(o['id'] for o in first.values())
third = key:value for key, value in second.items() if value['id'] not in first_ids

如您所见,我们遍历first 字典一次以构建我们的ID 集。这可以用来快速测试在second 字典中接收到的新数据是否是新的。如果是,我们将其添加到字典third

【讨论】:

以上是关于比较两个 JSON 结果并生成新条目的新 JSON (Python)的主要内容,如果未能解决你的问题,请参考以下文章

Normalizr 更改原始文件 .json 或生成具有所需架构的新文件 .json?

HTML5——JSON的新方法

如何比较两个json的数据并根据结果在vue中显示图标?

使用 Jackson 忽略 JSON 对象上的新字段 [重复]

比较两个 JSON 对象,而不考虑其中的元素序列

比较两个 NSDictionaries 并找出差异