Переместить несколько элементов (на основе критериев) в конец списка

#python #list #python-2.7

#python #Список #python-2.7

Вопрос:

У меня есть следующие 2 списка Python:

 main_l = ['Temp_Farh', 'Surface', 'Heater_back', 'Front_Press',
'Lateral_Cels', 'Gauge_Finl','Gauge_Relay','Temp_Throw','Front_JL']
hlig = ['Temp', 'Lateral', 'Heater','Front']
  

Мне нужно переместить элементы из main_l в конец списка, если они содержат строки, перечисленные hlig в.

Окончательная версия main_l должна выглядеть следующим образом:

 main_l = ['Surface', 'Gauge_Finl','Gauge_Relay', 'Temp_Farh', 'Heater_back', 'Front_Press',
'Lateral_Cels', 'Temp_Throw','Front_JL']
  

Моя попытка:

Сначала я пытаюсь определить main_l , содержит ли список элементы с подстрокой, перечисленные во 2-м списке hlig . Вот как я это делаю:

 `found` = [i for e in hlig for i in main_l if e in i]
  

found является подсписком main_l . Проблема в том, что теперь, когда у меня есть этот список, я не знаю, как выбрать элементы, которые НЕ содержат подстрок hlig . Если бы я мог это сделать, я мог бы добавить их в список not_found , а затем объединить их следующим образом: not_found found — и это дало бы мне то, что я хочу.

Вопрос:

Есть ли способ переместить соответствующие элементы в конец списка main_l ?

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

1. Всегда ли элементы во втором списке являются префиксами, разделенными символом подчеркивания?

2. Нет. Иногда перед ними не ставится символ подчеркивания.

Ответ №1:

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

 main_l.sort(key=lambda x: any(term in x for term in hlig))
  

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

1. Вы можете убрать квадратные скобки, чтобы немного уменьшить визуальный шум и включить any() короткое замыкание.

2. Первое решение стабильно. Нет необходимости во втором.

3. Упс, я предполагал, что это не так. Исправлено.

4. А? Когда я пытаюсь print main_l.sort(key=lambda x: any(term in x for term in hlig)) , я получаю None . PS: я использую Python 2.7

5. sort не возвращает отсортированный список; он сортирует его на месте. Если вы хотите, чтобы он возвращал новый список, используйте sorted вместо этого.

Ответ №2:

Я бы переписал то, что вам нужно:

 main_l = ['Temp_Farh', 'Surface', 'Heater_back', 'Front_Press', 'Lateral_Cels', 'Gauge_Finl','Gauge_Relay','Temp_Throw','Front_JL']
hlig = ['Temp', 'Lateral', 'Heater','Front']

found = [i for i in main_l if any(e in i for e in hlig)]
  

Тогда решение очевидно:

 not_found = [i for i in main_l if not any(e in i for e in hlig)]
answer = not_found   found
  

РЕДАКТИРОВАТЬ: удалены квадратные скобки вокруг понимания списка на основе комментариев Свена Марнаха (к решению aviraldg)

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

1. if not any !!!! Вот и все!!! О, это расстраивает! Большое спасибо. Это должно было быть так, как я это сделал. Я попытался изменить свой подход на включение if e not in i , но это дало список, который был намного длиннее, чем main_l — очевидно, это не работало. Еще раз спасибо, что показали правильный способ сделать это.

2. @WR Решение с использованием сортировки быстрее, лаконичнее и изменяет список на месте, поэтому вам также следует его рассмотреть.

3. Согласен, но спасибо за ваш пост. Это поможет мне в других сценариях.

4. @SvenMarnach, спасибо за предложение убрать скобки (хотя оно и не было направлено на мое решение). Сортировка может быть быстрее, когда main_l достаточно короткий, но в какой-то момент, по мере роста main_l, я ожидаю, что сортировка будет медленнее. Конечно, сортировка более элегантна.

5. @jimhark Я не думаю, что это будет медленнее для любого размера. Ключевая функция вычисляется только один раз для каждого элемента, и фактическая сортировка выполняется по возвращенным значениям ключа. Существует только два возможных значения ключа, False и True , и для массивов с этим свойством алгоритм Timsort, используемый методом Python list.sort() , по существу равен O (n) .