Какой наиболее эффективный способ найти индекс элемента из списка списков и не-списков?

#python #list #indexing #lambda

#python #Список #индексирование #лямбда

Вопрос:

У меня есть следующий список:

['F1', [10, 'r'], 'F2', 'F5', [15, 'w'] 'F3', [14, 'r'], 'F4']

Я хочу, чтобы индекс списка [15, 'w'] использовал значение 15.
Какой был бы наиболее эффективный способ получения значения индекса? (ответ должен быть 4)

Я попытался использовать lambda x: x[0] внутри функции python .index() , но не смог найти ничего ценного. Я не хочу использовать циклы и операторы if. Есть ли способ эффективно выполнить эту задачу, используя встроенные функции Python?

Первое значение каждого списка будет уникальным для всех списков внутри основного списка.

Редактировать:
Говоря «я не хочу использовать циклы», я имел в виду вложенные циклы и операторы if, которые увеличивают сложность решения, поскольку я буду работать с очень большими списками во многих местах кода. Таким образом, один цикл будет в порядке, если сложность не сильно увеличивается.

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

1. Я не хочу использовать циклы … , почему?

2. @RoadRunner Я отредактировал и объяснил свои потребности более подробно в вопросе 🙂

3. @theishita количество циклов не требует затрат на производительность, все зависит от того, насколько расточительны шаги внутри них

Ответ №1:

Здесь нельзя избежать циклов. Ваше утверждение «Я не хочу использовать циклы» следует заменить на «Я хочу довести все циклы до уровня C». Но, к сожалению, это плохая идея, потому что ваши типы данных не сбалансированы. Хотя я продемонстрирую свой векторизованный (C-level) подход:

 def cindex(x):
    x = np.array(x, dtype='O') #forcing all the items to be 'object' type
    f = np.vectorize(lambda x: isinstance(x, list)) #convert pyfunc to numpy accepted func
    list_idx, = np.where(f(x)) #identify indices of x items that are lists
    y = np.array(x[f(x)].tolist()) #filter y to contain only lists
    equality_idx, = np.where(y[:,0]=='15') #identify indices of y where first item is '15'
    return np.arange(len(x))[list_idx][equality_idx]
  

Теперь давайте сравним это с решением @AlexisG, которое, я думаю, является стандартным в данном случае. Потребовалось около 2ms , чтобы запустить его с вводом, содержащим 8000 элементов (и только последний элемент был правильным).

  • Приведение всех элементов к типу ‘object’ занимает 70% этого времени.
  • Преобразование pyfunc в векторизованную функцию не требует затрат
  • Применение этой функции по ячейкам занимает > 100% этого времени, это медленно.
  • Создание списка элементов типа list не требует затрат, но для преобразования обратно в массив numpy требуется около 200% этого времени [[10, 'r'], [15, 'w'], ...
  • Все дальнейшие операции, такие как поиск элементов, начинающихся с 15, и извлечение индексов, могут быть интерпретированы как бесплатные, потому что это уже уровень C.

В целом, алгоритм в 3-4 раза медленнее, поэтому избегайте numpy массивов, когда ваши типы данных несбалансированы.

Ответ №2:

Я знаю, что есть циклы. Но я хотел попрактиковаться в понимании списка на вашем примере.

 list_ = ['F1', [10, 'r'], 'F2', 'F5', [15, 'w'], 'F3', [14, 'r'], 'F4']
index = next((key for key, value in enumerate(list_) if type(value) == list for i_ in value if i_ == 15), None)