#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)