Исключить один список в соответствии с другим списком в Python

#python-3.x #list

#python-3.x #Список

Вопрос:

У меня есть такой двумерный список

 x_irp_group = [['x1_1_4', 'x1_2_4', 'x1_3_4', 'x1_4_4', 'x1_5_4', 'x1_6_4', 'x1_7_4', 'x1_8_4', 'x1_9_4', 'x1_10_4', 'x1_1_5', 'x1_2_5', 'x1_3_5', 'x1_4_5', 'x1_5_5', 'x1_6_5', 'x1_7_5', 'x1_8_5', 'x1_9_5', 'x1_10_5', 'x1_1_6', 'x1_2_6', 'x1_3_6', 'x1_4_6', 'x1_5_6', 'x1_6_6', 'x1_7_6', 'x1_8_6', 'x1_9_6', 'x1_10_6', 'x1_1_7', 'x1_2_7', 'x1_3_7', 'x1_4_7', 'x1_5_7', 'x1_6_7', 'x1_7_7', 'x1_8_7', 'x1_9_7', 'x1_10_7', 'x1_1_8', 'x1_2_8', 'x1_3_8', 'x1_4_8', 'x1_5_8', 'x1_6_8', 'x1_7_8', 'x1_8_8', 'x1_9_8', 'x1_10_8'], ['x1_1_8', 'x1_2_8', 'x1_3_8', 'x1_4_8', 'x1_5_8', 'x1_6_8', 'x1_7_8', 'x1_8_8', 'x1_9_8', 'x1_10_8', 'x1_1_9', 'x1_2_9', 'x1_3_9', 'x1_4_9', 'x1_5_9', 'x1_6_9', 'x1_7_9', 'x1_8_9', 'x1_9_9', 'x1_10_9', 'x1_1_10', 'x1_2_10', 'x1_3_10', 'x1_4_10', 'x1_5_10', 'x1_6_10', 'x1_7_10', 'x1_8_10', 'x1_9_10', 'x1_10_10', 'x1_1_11', 'x1_2_11', 'x1_3_11', 'x1_4_11', 'x1_5_11', 'x1_6_11', 'x1_7_11', 'x1_8_11', 'x1_9_11', 'x1_10_11', 'x1_1_12', 'x1_2_12', 'x1_3_12', 'x1_4_12', 'x1_5_12', 'x1_6_12', 'x1_7_12', 'x1_8_12', 'x1_9_12', 'x1_10_12']]
  

Я хочу исключить этот двумерный список, если элементы в другом одномерном списке, подобном этому

 x_irp_eliminated_list =   ['x1_1_4', 'x1_1_8', 'x1_1_12', 'x1_1_16', 'x1_1_19', 'x1_1_22', 'x1_1_26', 'x1_1_30', 'x1_1_34', 'x1_1_37', 'x1_1_43', 'x1_1_49', 'x1_1_55', 'x1_1_61', 'x1_1_68', 'x1_1_75', 'x1_1_81', 'x1_1_87', 'x1_1_92', 'x1_1_96', 'x1_1_101', 'x1_1_107', 'x1_1_112', 'x1_1_116', 'x1_1_121', 'x1_1_126', 'x1_1_131', 'x1_1_134', 'x1_1_137', 'x1_1_141', 'x1_1_145', 'x1_1_149', 'x1_1_152', 'x1_1_155', 'x1_1_160', 'x1_1_164', 'x1_1_169', 'x1_1_173', 'x1_1_181', 'x1_1_189', 'x1_1_197', 'x1_1_205', 'x1_2_8', 'x1_2_10', 'x1_2_13', 'x1_2_17', 'x1_2_21', 'x1_2_25', 'x1_2_28', 'x1_2_30', 'x1_2_34', 'x1_2_40', 'x1_2_45', 'x1_2_51', 'x1_2_58', 'x1_2_66', 'x1_2_71', 'x1_2_77', 'x1_2_82', 'x1_2_86', 'x1_2_91', 'x1_2_97', 'x1_2_102', 'x1_2_106', 'x1_2_111', 'x1_2_117', 'x1_2_122', 'x1_2_125', 'x1_2_129', 'x1_2_132', 'x1_2_135', 'x1_2_139', 'x1_2_143', 'x1_2_147', 'x1_2_151', 'x1_2_154', 'x1_2_157', 'x1_2_161', 'x1_2_166', 'x1_2_172', 'x1_2_177', 'x1_2_181', 'x1_2_189', 'x1_2_197', 'x1_2_205', 'x1_2_214', 'x1_3_1', 'x1_3_4', 'x1_3_8', 'x1_3_11', 'x1_3_15', 'x1_3_18', 'x1_3_22', 'x1_3_25', 'x1_3_28', 'x1_3_32', 'x1_3_35', 'x1_3_39', 'x1_3_42', 'x1_3_46', 'x1_3_49', 'x1_3_52', 'x1_3_56', 'x1_3_59', 'x1_3_63', 'x1_3_66', 'x1_3_70', 'x1_3_73', 'x1_3_77', 'x1_3_81', 'x1_3_85', 'x1_3_88', 'x1_3_91', 'x1_3_94', 'x1_3_97', 'x1_3_101', 'x1_3_105', 'x1_3_109', 'x1_3_112', 'x1_3_115', 'x1_3_118', 'x1_3_122', 'x1_3_126', 'x1_3_130', 'x1_3_134', 'x1_3_137', 'x1_3_140', 'x1_3_143', 'x1_3_147', 'x1_3_151', 'x1_3_156', 'x1_3_159', 'x1_3_163']
  

Я пишу такой код, но он не работает хорошо.

 x_final = [i for i, j in zip(x_irp_group, x_irp_eliminated_list) if i == j]
  

Я сокращаю списки. Обычно их размеры намного больше

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

1. представляют ли они наборы или важен порядок? операции набора значительно упростили бы это, потому что я думаю, вы можете просто {1,2,3,4} - {3,2} удалить элементы.

2. порядок важен. Например, x1_2_4 отсутствует во втором списке. Поэтому код должен удалить его из x_irp_group.

3. но важно, что x1_2_4 стоит x1_3_4 перед списком? если порядок элементов не имеет значения (или иногда вы просто хотите перебрать его отсортированным), то использование наборов может быть более подходящим подходом здесь.

4. sorted функция существует, поэтому, если большинство операций проще с наборами (например, исключение, пересечение, объединение и т. Д.), И иногда вам нужно перебирать ее, чтобы вы просто сортировали ее по мере необходимости, тогда, возможно, это был бы правильный путь, но если вы, очевидно, не выполняете такие действиятогда, возможно, следует придерживаться того, что вы делаете. В любом случае удаляемые элементы определенно представляют собой набор, поэтому вы, вероятно, захотите сохранить этот набор.

5. на самом деле лучше всего, вероятно, использовать SortedSet , если вы хорошо используете сторонний модуль, получите лучшее из обоих миров 🙂

Ответ №1:

понимание списка, которое у вас есть, не работает, потому что вы объединяете элементы вместе, что не является тем, что представляет операция (они не являются параллельными массивами), что вы хотите, это что-то вроде:

 x_final = [i for i in x_irp_group[0] if (i not in x_irp_eliminated_list)]
  

Обратите внимание, что для 2d-списка вам может потребоваться вложить это как:

 # writing normal loops you'd write:
# for row in x_irp_group:
#     for i in row:
#         if (...):
# so I typically try to indent the loops similarly since nested array comprehension
# gets complicated, honestly I'd likely prefer using generator functions for this anyway
x_final = [[i   for i in row
                    if (i not in x_irp_eliminated_list)
           ]for row in x_irp_group   
          ]
  

хотя я знаю, что i not in x_irp_eliminated_list это будет очень медленно для списка, изменение его на set улучшит производительность:

 x_irp_eliminated_set = set(x_irp_eliminated_list)
x_final = [i for i in x_irp_group[0] if (i not in x_irp_eliminated_set)]
  

Или, если списки тривиально отсортированы, вы можете преобразовать их оба в наборы, выполнить вычитание, а затем отсортировать его снова:

 x_final = [ sorted(set(x_irp_group[0]) - set(x_irp_eliminated_list)) ] 
  

хотя, если у вас есть супер гигантские списки, это, вероятно, было бы менее желательно.

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

1. Я использовал это для более быстрой работы. Установленный подход сделал это быстрее. Спасибо за эту информацию. Я узнаю одну новую вещь. Но это создает одномерный список. Я хотел бы создать двумерный список, подобный исходному x_irp_group

2. Я отредактировал вложенное понимание, потому что первая версия неправильно сворачивала измерение, работает ли версия, начинающаяся с [[I for I in row , некорректно?

Ответ №2:

 x_irp_eliminated_list_set = set(x_irp_eliminated_list)
x_last = [i for row in x_irp_group
         for i in row 
         if (i in x_irp_eliminated_list_set)]
print(x_last[:30])
  

Я использовал это для более быстрой работы. Установленный подход сделал это быстрее. Спасибо за эту информацию. Я узнаю одну новую вещь. Но это создает одномерный список. Я хотел бы создать двумерный список, подобный исходному x_irp_group