简体   繁体   中英

Find index of a sublist in a list

Trying to find the index of a sublists with an element. I'm not sure how to specify the problem exactly (which may be why I've overlooked it in a manual), however my problem is thus:

list1 = [[1,2],[3,4],[7,8,9]]

I want to find the first sub-list in list1 where 7 appears (in this case the index is 2, but lll could be very very long). (It will be the case that each number will appear in only 1 sub-list – or not at all. Also these are lists of integers only) Ie a function like

spam = My_find(list1, 7)

would give spam = 2 I could try looping to make a Boolean index

[7 in x for x in lll]

and then .index to find the 'true' - (as per Most efficient way to get indexposition of a sublist in a nested list ) However surely having to build a new boolean list is really inefficient..

My code starts with list1 being relatively small, however it keeps building up (eventually there will be 1 million numbers arranged in approx. 5000 sub-lists of list1

Any thoughts?

I could try looping to make a Boolean index

[7 in x for x in lll]

and then .index to find the 'true' … However surely having to build a new boolean list is really inefficient

You're pretty close here.

First, to avoid building the list, use a generator expression instead of a list comprehension, by just replacing the [] with () .

sevens = (7 in x for x in lll)

But how do you do the equivalent of .index when you have an arbitrary iterable, instead of a list? You can use enumerate to associate each value with its index, then just filter out the non-sevens with filter or dropwhile or another generator expression, then next will give you the index and value of the first True .

For example:

indexed_sevens = enumerate(sevens)
seven_indexes = (index for index, value in indexed_sevens if value)
first_seven_index = next(seven_indexes)

You can of course collapse all of this into one big expression if you want.

And, if you think about it, you don't really need that initial expression at all; you can do that within the later filtering step:

first_seven_index = next(index for index, value in enumerate(lll) if 7 in value)

Of course this will raise a StopIteration exception instead of a ValueError expression if there are no sevens, but otherwise, it does the same thing as your original code, but without building the list, and without continuing to test values after the first match.

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