В python, учитывая список списков, как вы определяете индекс соответствующего элемента?

#python #list #enumerate

#питон #Список #перечислять

Вопрос:

 >>> birds = ['duck', 'chicken', 'goose']
>>> cats = ['tiger', 'lion']
>>> humans = ['human']
>>> at_the_zoo = [birds, cats, humans]
 

Учитывая список списков, подобных at_the_zoo, как мне определить, в каком списке находится tiger?

 for animal in sum(at_the_zoo, []):
    if "tiger" == animal:
        print "1 help!"
 

Например, я могу найти tiger в списке животных, и если я использую enumerate, он сообщит мне, что он находится под индексом 3. Как мне выяснить, что он является частью элемента 1 списка at_the_zoo.
поиск duck подскажет мне элемент 0 и т.д.

Спасибо!

Комментарии:

1. Я думаю, что связанный ответ на самом деле не является дубликатом. Другой вопрос имеет произвольную вложенность, и это один уровень вложенности. Лучший ответ на каждый из них отличается. Я назначаю повторное открытие…

Ответ №1:

Я бы подумал что-то вроде:

 def find_element(nested_lst, what):
    for idx, sublst in enumerate(nested_lst):
        try:
            idx2 = sublst.index(what)
            return (idx, idx2)
        except ValueError:
            pass
 

должно работать.

пример:

 >>> def find_element(nested_lst, what):
...     for idx, sublst in enumerate(nested_lst):
...         try:
...             idx2 = sublst.index(what)
...             return (idx, idx2)
...         except ValueError:
...             pass
... 
>>> birds = ['duck', 'chicken', 'goose']
>>> cats = ['tiger', 'lion']
>>> humans = ['human']
>>> find_element([birds, cats, humans], 'human')
(2, 0)
>>> find_element([birds, cats, humans], 'gator')  # returns None if not found.
>>> find_element([birds, cats, humans], 'tiger')
(1, 0)
 

Стоит отметить, что в среднем list.index выполняется операция O (N), что означает, что списки не являются наиболее эффективной структурой данных для тестирования членства. если ваши фактические данные поддерживают это, возможно, стоит рассмотреть возможность использования a set вместо этого.

Комментарии:

1. Обратите внимание, что если все, что вас волнует , это индекс sublst содержащего what , а не индекс what внутри sublst , вы можете просто сказать if what in sublst: return idx , вместо того, чтобы использовать try / except block в сочетании с. sublst.index Это не изменит эффективность, но, возможно, выглядит немного приятнее.

2. @дано — Справедливое замечание. По какой-то причине у меня сложилось впечатление, что ОП хотел и того, и другого.

3. Мне понравился этот ответ, потому что он указывал на структуру данных наборов, которую, вероятно, было бы правильно использовать. Решение с предложенной правкой дано сработало! 🙂 Я бы отредактировал предложение дано, если это возможно. В противном случае спасибо! В моей программе я в конечном итоге придерживался списков

Ответ №2:

Просто создайте индекс:

 >>> birds = ['duck', 'chicken', 'goose']
>>> cats = ['tiger', 'lion']
>>> humans = ['human']
>>> at_the_zoo = [birds, cats, humans]
>>> index = {}
>>> for i, arr in enumerate(at_the_zoo):
...   index.update(zip(arr, [i]*len(arr)))
...
>>> index
{'tiger': 1, 'goose': 0, 'lion': 1, 'human': 2, 'duck': 0, 'chicken': 0}
>>> index.get('tiger')
1
>>>
 

Или:

 >>> for i, arr in enumerate(at_the_zoo):
...   arr_len = len(arr)
...   index.update(zip(arr, zip([i]*arr_len, range(arr_len))))
...
>>> from pprint import pprint
>>> pprint(index)
{'chicken': (0, 1),
 'duck': (0, 0),
 'goose': (0, 2),
 'human': (2, 0),
 'lion': (1, 1),
 'tiger': (1, 0)}
>>> index.get('tiger')
(1, 0)
 

Ответ №3:

Два опубликованных ответа — find, но @newtover’s на мой вкус слишком загадочен, а @mgilson’s не отвечает на заданный вопрос. Позвольте мне попробовать это сделать.

 def find_in_inner(lst, target):
    for i, sublst in enumerate(lst):
        if target in sublst:
            return i

>>> birds = ['duck', 'chicken', 'goose']
>>> cats = ['tiger', 'lion']
>>> humans = ['human']
>>> at_the_zoo = [birds, cats, humans]
>>> find_in_inner(at_the_zoo, "tiger")
1
 

Ответ №4:

Для конкретного случая списка списков, если вам нужен кортеж из номера подсписка и индекса в этом подсписке, вы можете сделать:

 [(i,j) for i, sl in enumerate(LoL) for j,e in enumerate(sl) if e==tgt]
 

ДЕМОНСТРАЦИЯ:

 >>> birds = ['duck', 'chicken', 'goose']
>>> cats = ['tiger', 'lion']
>>> humans = ['human']
>>> zoo = [birds, cats, humans]
>>> tgt='lion'
>>> [(i,j) for i, sl in enumerate(zoo) for j,e in enumerate(sl) if e==tgt]
[(1, 1)]
 

Это правильно обрабатывает потенциальный случай нескольких целей в подсписках.

Если вы знаете, что вас интересует только первый экземпляр, вы можете сделать:

 [(i,sl.index(tgt)) for i, sl in enumerate(zoo) if tgt in sl] 
 

Если вас не волнует, что дубликаты устраняются, и вам нужен быстрый доступ, вы можете создать индекс:

 {e:(i,j) for i, sl in enumerate(zoo) for j, e in enumerate(sl)}
# {'tiger': (1, 0), 'goose': (0, 2), 'lion': (1, 1), 'human': (2, 0), 'duck': (0, 0), 'chicken': (0, 1)}
 

Предположим, что в каждом случае есть человек, кошка и птица по имени «боб»:

 birds = ['duck', 'chicken', 'goose', 'bob']
cats = ['tiger', 'lion','bob']
humans = ['human','bob']
 

Таким образом, вы можете создать индекс, который правильно обрабатывает несколько записей в нескольких подсписках:

 index={}
for i, sl in enumerate(zoo):
    for j, item in enumerate(sl):
        index.setdefault(item, []).append((i,j))
 

Индекс становится:

   {'tiger': [(1, 0)], 
   'goose': [(0, 2)], 
   'lion': [(1, 1)], 
   'human': [(2, 0)], 
   'duck': [(0, 0)], 
   'chicken': [(0, 1)], 
   'bob': [(0, 3), (1, 2), (2, 1)]}