1

I have a .NET structure that has arrays with arrays in it. I want to crete a list of members of items from a specific array in a specific array using list comprehension in IronPython, if possible.

Here is what I am doing now:

tag_results = [item_result for item_result in results.ItemResults if item_result.ItemId == tag_id][0]
tag_vqts = [vqt for vqt in tag_results.VQTs]
tag_timestamps = [vqt.TimeStamp for vqt in tag_vqts]

So, get the single item result from the results array which matches my condition, then get the vqts arrays from those item results, THEN get all the timestamp members for each VQT in the vqts array.

Is wanting to do this in a single statement overkill? Later on, the timestamps are used in this manner:

vqts_to_write = [vqt for vqt in resampled_vqts if not vqt.TimeStamp in tag_timestamps]

I am not sure if a generator would be appropriate, since I am not really looping through them, I just want a list of all the timestamps for all the item results for this item/tag so that I can test membership in the list.

I have to do this multiple times for different contexts in my script, so I was just wondering if I am doing this in an efficient and pythonic manner. I am refactoring this into a method, which got me thinking about making it easier.

FYI, this is IronPython 2.6, embedded in a fixed environment that does not allow the use of numpy, pandas, etc. It is safe to assume I need a python 2.6 only solution.

My main question is:

Would collapsing this into a single line, if possible, obfuscate the code?

If collapsing is appropriate, would a method be overkill?

Two! My two main questions are:

Would collapsing this into a single line, if possible, obfuscate the code?

If collapsing is appropriate, would a method be overkill?

Is a generator appropriate for testing membership in a list?

Three! My three questions are... Amongst my questions are such diverse queries as...I'll come in again...

(it IS python...)

noelhx
  • 111
  • 10

1 Answers1

1

tag_results = [...][0] builds a whole new list just to get one item. This is what next() on a generator expression is for:

next(item_result for item_result in results.ItemResults if item_result.ItemId == tag_id)

which only iterates just enough to get a first item.

You can inline that, but I'd keep that as a separate expression for readability.

The remainder is easily put into one expression:

tag_results = next(item_result for item_result in results.ItemResults 
                   if item_result.ItemId == tag_id)
tag_timestamps = [vqt.TimeStamp for vqt in tag_results.VQTs]

I'd make that a set if you only need to do membership testing:

tag_timestamps = set(vqt.TimeStamp for vqt in tag_results.VQTs)

Sets allow for constant time membership tests; testing against a list takes linear time as the whole list could end up being scanned for each such test.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    Excellent information! I am slowly learning about the standard library as I come across the need for things, but sometimes, unless I stumble on it randomly browsing the docs or remember a few minutes from an online video I saw months ago, I forget things until I put them in practice. This was the information I needed. I also noted `frozenset` for immutable lists, which the majority of mine are. Thank you! – noelhx Jul 31 '16 at 23:47