1

With the following list of dict:

[ {'isn': '1', 'fid': '4', 'val': '1', 'ptm': '05/08/2019 14:22:39', 'sn': '111111'  'procesado': '0'}, 
 {'isn': '1', 'fid': '4', 'val': '0', 'ptm': '05/08/2019 13:22:39', 'sn': '111111', 'procesado': '0'},
<...> ] 

I would need to compare for each dict of the list if there are other element with:

  • equal fid
  • equal sn
  • distinct val (if val(elemX)=0 then val(elemY)=1)
  • distinct ptm (if val=0 of elemX then ptm of elemX < ptm of elemY)

This could be done in a traditional way using an external for loop an internal while, but this is not the optimal way to do it.


Trying to find a way to do that, I tried with something like this:

   for p in lista:
        print([item for item in lista if ((item["sn"] == p["sn"]) & (item["val"] == 0) & (p["val"] == 1) & (
               datetime.strptime(item["ptm"], '%d/%m/%Y %H:%M:%S') < datetime.strptime(p["ptm"],'%d/%m/%Y %H:%M:%S')))])

But this does not work (and also is not optimal)

IoT user
  • 1,222
  • 4
  • 22
  • 49

1 Answers1

1

Just build a mapping from (fid,sn,val) onto a list of candidates (the whole dict, its index, or just its ptm (shown below), depending on what output you need). Also check whether any of its opposite numbers (under (fid,sn,!val)) are already present and do the ptm comparison if so:

seen={}
for d in dd:
  f=d['fid']; s=d['sn']; v=int(d['val'])
  p=datetime.strptime(d['ptm'],'%d/%m/%Y %H:%M:%S')
  for p0 in seen.get((f,s,not v),()):
    if p0!=p and (p0<p)==v: …
  seen.setdefault((f,s,v),[]).append(p)

If you have a large number of values with the same key, you could use a tree to hasten the ptm comparisons, but that seems unlikely here. Using real data types for the individual values, and perhaps a namedtuple to contain them, would of course make this a lot nicer.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76