Python: Indexing list for element in nested list

17,831

Solution 1

In Python 2.6 or better,

next((i for i, sublist in enumerate(nested_list) if "a" in sublist), -1)

assuming e.g. you want a -1 result if 'a' is present in none of the sublists.

Of course it can be done in older versions of Python, too, but not quite as handily, and since you don't specify which Python versions you're interested in, I think it's best to use the latest production-solid one (just edit your answer if you need to specify other, older versions of Python).

Edit: per request, let me try to explain how this work. I'm using the (new in 2.6) built-in function next, specifically I'm calling next(iterator, default): returns the next item of the iterator (and thus the first, since this is the first time we're advancing that iterator), or the default value if the iterator's finished (which means "empty" if it's finished before we ever advanced it;-). The default is clearly that -1 and gets returned if "a is present in none of the sublists", which means the same as "the iterator is empty" in this case.

Let's look at the iterator again:

(i for i, sublist in enumerate(nested_list) if "a" in sublist)

the (rounded) parentheses and for and if keywords mean this is a generator expression, also known for brevity as genexp. i (the index) and sublist (the item at that index) advance over enumerate(nested_list) -- if we didn't have enumerate here then we wouldn't be keeping track of the index, but in this case we do need it. They're only considered when the if clause is satisfied, that is, when the element you're looking for is present in the current sublist.

So this genexp produces, one at a time, each value of the index such that the sublist at that index satisfies the condition "a" in sublist. Since we're using it inside next, we only take the first such index.

The OP might be justified for thinking that a magical builtin doing all of this in three or four characters would be handier -- and so it would, for this very specific requirement, which I believe I've never met before in over ten years of use of Python; however, if every such specific requirement had its own very specialized builtin the language and builtins would grown to be larger than the tax code. Instead, Python offers many lower-level "lego bricks" and a few handy way to snap them together, to clearly (and reasonably concisely) express the solution to a combinatorially-large variety of specific requirements, like the OP's.

Solution 2

You'll need to use a looping construct of some sort:

next((sublist for sublist in mainlist if item in sublist))

That will give you a generator for all sublists containing the item you want, and give you the first one.

Share:
17,831
aquateenfan
Author by

aquateenfan

Updated on July 19, 2022

Comments

  • aquateenfan
    aquateenfan almost 2 years

    I know what I'm looking for. I want python to tell me which list it's in.

    Here's some pseudocode:

    item = "a"
    
    nested_list = [["a", "b"], ["c", "d"]]
    
    list.index(item) #obviously this doesn't work
    

    here I would want python to return 0 (because "a" is an element in the first sub-list in the bigger list). I don't care which sub-element it is. I don't care if there are duplicates, e.g., ["a", "b", "a"] should return the same thing as the above example.

  • Alex Martelli
    Alex Martelli about 14 years
    Yep: this gives the sublist, while the OP specified they want the INDEX of that sublist, as I return in my answer.