如何有选择地附加列表?

How to append a list selectively?

我正在通过 RFID reader 接收消息。我想做的是删除重复项并仅在满足两个条件的情况下附加到列表中:

  1. 如果他们的 ID(在本例中为 epc)是唯一的,并且 (完成)
  2. datetime 是在 5 分钟间隔之后(所以我可以跟踪同一标签仍然被 RFID reader 每 5 分钟读取一次)

    import paho.mqtt.client as mqtt
    import json
    
    testlist = []       
    
    def on_message(client, userdata, msg):
        payloadjson = json.loads(msg.payload.decode('utf-8'))
        line = payloadjson["value"].split(',')
        epc =  line[1]
        datetime = payloadjson['datetime']
        # datetime is in this string format '2016-04-06 03:21:17'
    
        payload = {'datetime': datetime, 'epc': epc[11:35]}
    
        # this if-statement satisfy condition 1
        if payload not in testlist:
            testlist.append(payload)
            for each in teslist:
                print (each)
    
    test = mqtt.Client(protocol = mqtt.MQTTv31)
    test.connect(host=_host, port=1883, keepalive=60, bind_address="")
    test.on_connect = on_connect
    test.on_message = on_message
    test.loop_forever() 
    

我怎样才能达到条件 2?

更新
对于我试图实现的目标不明确,我深表歉意

我想要的输出看起来像这样:

{'datetime': 2016-04-06 03:21:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:21:18', 'epc': 00000002} # from Tag B
...
...
# 5 minutes later
{'datetime': 2016-04-06 03:21:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:21:18', 'epc': 00000002} # from Tag B
{'datetime': 2016-04-06 03:26:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:26:18', 'epc': 00000002} # from Tag B
...
...
# Another 5 minutes later
{'datetime': 2016-04-06 03:21:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:21:18', 'epc': 00000002} # from Tag B
{'datetime': 2016-04-06 03:26:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:26:18', 'epc': 00000002} # from Tag B
{'datetime': 2016-04-06 03:31:17', 'epc': 00000001} # from Tag A
{'datetime': 2016-04-06 03:31:18', 'epc': 00000002} # from Tag B
...
...

这可能是一种更简单的方法:

class EPC(object):
    def __init__(self, epc, date):
        self.epc = epc
        self.datetime = date
    def __eq__(self, other):
        difference = datetime.strptime(self.datetime, '%Y-%m-%d %H:%M:%S') - datetime.strptime(other.datetime, '%Y-%m-%d %H:%M:%S')
        return self.epc == other.epc and timedelta(minutes=-5) < difference < timedelta(minutes=5)
    def __ne__(self, other):
        difference = datetime.strptime(self.datetime, '%Y-%m-%d %H:%M:%S') - datetime.strptime(other.datetime, '%Y-%m-%d %H:%M:%S')
        return self.epc != other.epc or (self.epc == other.epc and (difference > timedelta(minutes=5) or difference < timedelta(minutes=-5))) 

payload = EPC(date, epc[11:35])
if payload not in test_list:
    test_list.append(payload)

我想知道 epc 值是否可以来回交替。也就是说,有没有可能先出现epc值'A',再出现epc值'B',再出现epc值'A'? (或者可能是 A、B、C 等?)

如果假设只有一个标签,那么只看最近的条目:

last_tag = testlist[-1]
last_dt = last_tag['datetime']

现在您可以将当前 datetime 与之前的值进行比较,看看它是否适合您的 window。

不过请注意,将日期时间代码放在 has 中实际上对您现有的代码不起作用,因为日期时间不断变化,因此 payload not in testlist 将始终为真,除非您获得两个 RFID在同一秒读取。

有几点可以解决您的问题:

  1. 为了 ID 的唯一性,您只需要检查 epc 字段,而不是整个 payload 对象,因为 payload 对象包含 datetime。您可以使用 set 来存储所有看到的 ID。
  2. 为了检查时间,使用datetimetimedelta对象比较时间
# -*- coding: utf-8 -*-
"""
06 Apr 2016
To answer 
"""

# Import statements

# import paho.mqtt.client as mqtt
import json
import datetime as dt

testlist = []
seen_ids = set()  # The set of seen IDs
five_minutes = dt.timedelta(minutes=5)  # The five minutes differences

def on_message(client, userdata, msg):
    payloadjson = json.loads(msg.payload.decode('utf-8'))
    line = payloadjson["value"].split(',')
    epc =  line[1]
    datetime = payloadjson['datetime']
    # datetime is in this string format '2016-04-06 03:21:17'

    # Convert the string into datetime object
    datetime = dt.datetime.strptime(datetime, '%Y-%m-%d %H:%M:%S')

    payload = {'datetime': datetime, 'epc': epc[11:35]}

    # this if-statement satisfy condition 1
    if payload['epc'] not in seen_ids:  # Need to use another set
        should_add = True               # The flag whether to add
        if len(testlist) > 0:
            last_payload = testlist[-1]
            diff = payload['datetime'] - last_payload['datetime']
            if diff < five_minutes:     # If the newer one is less than five minutes, do not add
                should_add = False
        if should_add:
            seen_ids.add(payload['epc'])    # Mark as seen
            testlist.append(payload)
            print ('Content of testlist now:')
            for each in testlist:
                print (each)

class Message(object):
    def __init__(self, payload):
        self.payload = payload

def main():
    test_cases = []
    for i in range(10):
        payload = '{{"value":",{}","datetime":"2016-04-06 03:{:02d}:17"}}'.format('0'*34+str(i), i)
        test_case = Message(payload)
        test_cases.append(test_case)
    for test_case in test_cases:
        on_message(None, None, test_case)

if __name__ == '__main__':
    main()

将打印:

Content of testlist now:
{'epc': u'000000000000000000000000', 'datetime': datetime.datetime(2016, 4, 6, 3, 0, 17)}
Content of testlist now:
{'epc': u'000000000000000000000000', 'datetime': datetime.datetime(2016, 4, 6, 3, 0, 17)}
{'epc': u'000000000000000000000005', 'datetime': datetime.datetime(2016, 4, 6, 3, 5, 17)}

你的问题有点不清楚。假设您想要更新测试列表,如果它是一个新的 epc,或者如果它自上次更新 epc 以来已经超过 5 分钟。 dict() 在这种情况下效果很好。使用标准库中的 datetime 模块计算日期或时间的差异。

import paho.mqtt.client as mqtt
import json
import datetime as dt

TIMELIMIT = dt.timedelta(minutes=5)

testlist = {}       ## <<-- changed this to a dict()

def on_message(client, userdata, msg):
    payloadjson = json.loads(msg.payload.decode('utf-8'))
    line = payloadjson["value"].split(',')
    epc =  line[1]

    # this converts the time stamp string to something python can
    # use in date / time calculations
    when = dt.datetime.strptime(payloadjson['datetime'], '%Y-%m-%d %H:%M:%S')

    if epc not in testlist or when - testlist[epc] > TIMELIMIT:
        testlist[epc] = when

        for epc, when in teslist.items():
            print (epc, when)