简体   繁体   中英

Python: Difference between two positions in one list depending on rule set for another list

Consider two lists of identical length:

  • t is a list of irregular-intervals of times in seconds, arranged chronologically
  • pt is a list of sequences of numbers 1,2,3 wsuch that a 1 is followed by a consecutive string of 2's, then followed by a 3.
    • 1 = start of event, 2 = continuation of event, 3 = end of event
    • This means that for a single event, the sequence begins with a single 1, is followed by a consecutive string of 2s (how many times it repeats will vary), and finally ends in a single 3.
    • There is more than 1 event contained in this vector

For example, the input could look like:

#    |--Event #1-|   |---Event #2----|   |Event #3 | 
pt = [1, 2,  2,  3,  1,  2,  2,  2,  3,  1,  2,  3 ]
t =  [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38] 

Is there a 1-liner that doesn't involve multiple nested loops that we could use that would calculate the difference in time values in t for each event sequence in pt ?

For example, the desired output for the above inputs would be a list of length 3 (because there are 3 events) where the output is

Output: [13, 20, 6]

### Explanation:
# 13 = 14-1  = t[position where pt shows first 3]  - t[position where pt shows first 1]
# 20 = 37-17 = t[position where pt shows second 3] - t[position where pt shows second 1]
# 6  = 38-32 = t[position where pt shows third 3]  - t[position where pt shows third 1]

using pure python :

pt = [1, 2,  2,  3,  1,  2,  2,  2,  3,  1,  2,  3 ]
t =  [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38]

l = [y for x, y in zip(pt,t) if x in [1,3]]

print([l[i:i+2][1] - l[i:i+2][0] for i in range(0, len(l), 2)])
[13, 20, 6]

using more_itertools.chunked() :

from more_itertools import chunked

print([y-x for x,y in chunked([y for x, y in zip(pt,t) if x in [1,3]], 2)])
[13, 20, 6]

explanation

If you look close, we see this list comprehension occurring multiple times. This is the center of the solution!

[y for x, y in zip(pt,t) if x in [1,3]]

So, what's going on?

Using the zip function, we make a list of the paired elements, and if the x element (1st list element pair) is either 1 or 3 we add it to the list.

This gives us a list of the differences we need to find.

#|---|  |----|  |----|
[1, 14, 17, 37, 32, 38]

Now comes the second part, getting the differences from these. We essentially need to make pairs from this, the method I'm going to use here is chunking. The pure python way to partition a list into chunks is as follows:

#given a list l
chunklen = 2 
[l[i:i+chunklen] for i in range(0, len(l), chunklen)]

using this we could partition the [1, 14, 17, 37, 32, 38] list to:

[[1, 14], [17, 37], [32, 38]]

but it's far simpler to just get the differences immediately!

l[i:i+chunklen][1]-l[i:i+chunklen][0]
#given l[i:i+chunklen] as [1, 14] this would return 14-1 i.e. 13

This seems to work

pt = [1, 2,  2,  3,  1,  2,  2,  2,  3,  1,  2,  3 ]
t =  [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38] 

st = 0
lst = []
for x in zip(pt,t):
   if x[0] == 1: st = x[1]
   if x[0] == 3: 
      d = x[1] - st
      lst.append(d)

print(lst)

Output

[13, 20, 6]

Code:

pt = [1, 2,  2,  3,  1,  2,  2,  2,  3,  1,  2,  3 ]
t =  [1, 10, 13, 14, 17, 20, 21, 25, 37, 32, 33, 38] 

events_t =[]
arr = []
for pt_ele, t_ele in zip(pt, t):
    arr.append(t_ele)
    if pt_ele == 3:
        events_t.append(arr)
        arr = []
print(events_t)
res = [i[-1] - i[0] for i in events_t]
print(res)

Output:

[[1, 10, 13, 14], [17, 20, 21, 25, 37], [32, 33, 38]]
[13, 20, 6]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM