-1

So, I have a list of dictionaries that constitutes frames information in the form of a list of dictionaries. list is sorted as per "frame_num" key

[
    { "frame_num": "1","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "2","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "3","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "4","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "6","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "8","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "10","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "15","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "16","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "18","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "20","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "22","width": "1920","height":"1080","other_info": "some_info" }
]

So, I want to fetch a list of frames who's frame_num values are in the range of 4:14 that is a slice of a list with this range my answer will be

[
    { "frame_num": "4","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "6","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "8","width": "1920","height":"1080","other_info": "some_info" },
    { "frame_num": "10","width": "1920","height":"1080","other_info": "some_info" },
]

one possible way could be with the help of list comprehension. But I want an efficient way of doing it since this list could have millions of frame info I wish to get some pythonic way of doing this.

1 Answers1

1

I assume that the last frame (12), is a typo, since you didn't take it in the output.

This is fairly easy with a list comprehension. First, define the range

r = range(4, 14)

Then, use the filter of the list comprehension to selected the frames:

selected_frames = [f for f in frames if int(f["frame_num"]) in r]
# [{'frame_num': '4', 'width': '1920', 'height': '1080', 'other_info': 'some_info'}, {'frame_num': '6', 'width': '1920', 'height': '1080', 'other_info': 'some_info'}, {'frame_num': '8', 'width': '1920', 'height': '1080', 'other_info': 'some_info'}, {'frame_num': '10', 'width': '1920', 'height': '1080', 'other_info': 'some_info'}]

Don't worry, in r is fast. But the conversion to an int will take some time.


If your frames are ordered and the range continuous (no step), you can use a regular loop and break when you exit the range:

selected_frames = []
for f in frames:
    if int(f["frame_num"]) in r:
        selected_frames.append(f)
    elif selected_frames: # not in range anymore
        break

(If you have a step, you can still manage to test the range boundaries, and then appply the step.)

I you have several ranges to take from the same frame list, maybe indexing that list could be an idea:

nums = [int(f["frame_num"]) for f in frames]
# [1, 2, 3, 4, 6, 8, 10, 15, 16, 18, 20]

You can now find the elements with a bisect:

import bisect
f = bisect.bisect_left(nums, 4)
t = bisect.bisect_left(nums, 14)
selected_frames = frames[f:t]
jferard
  • 7,835
  • 2
  • 22
  • 35
  • thanks, @jferard. this answer really helped me a lot to understand more about python. keep enlightening. – Roshan Chauhan Sep 30 '20 at 07:42
  • @RoshanChauhan Glad to help. If you think this answered your question, please accept my answer (that's another way to say "thanks" on StackOverflow). – jferard Sep 30 '20 at 15:30