Python - найти индекс элемента в списке списков - PullRequest
13 голосов
/ 04 марта 2012

У меня есть список списков:

colours=[["#660000","#863030","#ba4a4a","#de7e7e","#ffaaaa"],["#a34b00","#d46200","#ff7a04","#ff9b42","#fec28d"],["#dfd248","#fff224","#eefd5d","#f5ff92","#f9ffbf"],["#006600","#308630","#4aba4a","#7ede7e","#aaffaa"]]

Какой самый чистый способ поиска в списке и возврата позиции одного из элементов, например, "#660000"

Я посмотрел на метод индекса, но, похоже, он не распаковывает список внутри списка.

postion=colours.index("#660000")

дает: ValueError: ['#660000'] is not in list, а не [0][0], как я ожидаю ...

Ответы [ 6 ]

15 голосов
/ 04 марта 2012

Я бы сделал что-то вроде этого:

[(i, colour.index(c))
 for i, colour in enumerate(colours)
 if c in colour]

Это вернет список кортежей, где первый индекс - это позиция в первом списке, а второй - позиция во втором списке (примечание:c - это цвет, который вы ищете, то есть "#660000").

Для примера в вопросе возвращается значение:

[(0, 0)]

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

next(((i, colour.index(c))
      for i, colour in enumerate(colours)
      if c in colour),
     None)

Это вернет кортеж для первого найденного элемента или None, если элемент не найден (Вы также можете удалить приведенный выше аргумент None, который вызовет исключение StopIteration, если элемент не найден).

Редактировать: Как правильно указывает @RikPoggi, если число совпадений велико, этовнесет некоторые издержки, потому что colour повторяется дважды, чтобы найти c.Я предположил, что это разумно для небольшого числа совпадений и иметь ответ в одном выражении.Однако, чтобы избежать этого, вы также можете определить метод, используя ту же идею следующим образом:

def find(c):
    for i, colour in enumerate(colours):
        try:
            j = colour.index(c)
        except ValueError:
            continue
        yield i, j

matches = [match for match in find('#660000')]

Обратите внимание, что, поскольку find является генератором, вы можете использовать его, как в примере выше с next остановиться на первом матче и пропустить взгляд дальше.

8 голосов
/ 04 марта 2012

Используя enumerate(), вы можете написать такую ​​функцию:

def find(target):
    for i,lst in enumerate(colours):
        for j,color in enumerate(lst):
            if color == "#660000":
                return (i, j)
    return (None, None)
4 голосов
/ 04 марта 2012

Было бы, возможно, более просто использовать numpy:

>>> import numpy
>>> ar = numpy.array(colours)
>>> numpy.where(ar=="#fff224")
(array([2]), array([1]))

Как видите, вы получите кортеж со всеми индексами строк и столбцов.

4 голосов
/ 04 марта 2012

Если вы хотите избежать повторения целевого подсписка дважды, кажется, что лучший (и самый Pythonic) способ - это цикл:

def find_in_sublists(lst, value):
    for sub_i, sublist in enumerate(lst):
        try:
            return (sub_i, sublist.index(value))
        except ValueError:
            pass

    raise ValueError('%s is not in lists' % value)
0 голосов
/ 29 ноября 2017

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

list_name[0].index("I want coffee")
0 голосов
/ 02 февраля 2016

В Python 3 я использовал этот шаблон:

CATEGORIES = [   
    [1, 'New', 'Sub-Issue', '', 1],
    [2, 'Replace', 'Sub-Issue', '', 5],
    [3, 'Move', 'Sub-Issue', '', 7],
]

# return single item by indexing the sub list
next(c for c in CATEGORIES if c[0] == 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...