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

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

我现在做的是:

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

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

我基本上是在监控这个 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.

所以这两个问题是:

  1. 有没有更好的方法来比较两个 JSON 对象中的两个相同条目(未排序)
  2. 有没有办法获得仅包含 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 中(新)

标签: python json discord


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多