2016-10-23 2 views
1

Я следующий список:Условный Постулаты относительно различных регулярных выражений и длины списка в Python

['E12.2', 'E16.1', 'E15.1'] 
    ['E10.1', 'I11.2', 'I10.1_27353757'] 
    ['E16.1', 'E18.1', 'E17.3'] 
    ['E1.8', 'I12.1_111682336', 'I12.1_111682195'] 
    ['E55.1', 'E57.1', 'E56.1','E88.1'] 
    ['U22.3', 'U22.6_13735517', 'U23.1'] 

и я хочу поставить условие, чтобы отфильтровать списки, которые имеют) длину, равную 3 б) не содержащий '_' c), не содержащий алфавита 'U' Я пытаюсь реализовать в одной строке, как мне это сделать? У меня есть следующее условие работы, и я знаю, что вы можете использовать модуль regex для соответствия регулярному выражению в списках, но могу ли я выполнить все условия в одной строке?

if(len(fin_list) == 3) 

ответ

2

Это один из возможных способов:

lists = [['E12.2', 'E16.1', 'E15.1'], 
     ['E10.1', 'I11.2', 'I10.1_27353757'], 
     ['E16.1', 'E18.1', 'E17.3'], 
     ['E1.8', 'I12.1_111682336', 'I12.1_111682195'], 
     ['E55.1', 'E57.1', 'E56.1','E88.1'], 
     ['U22.3', 'U22.6_13735517', 'U23.1']] 

for lst in lists: 
    if len(lst) != 3 and not any('_' in item or 'U' in item for item in lst): 
     print(lst) 

# Output: 
# ['E55.1', 'E57.1', 'E56.1', 'E88.1'] 

Интересный бит здесь является использование any над выражением генератора. Чтобы разбить его, это повторяется по каждому item в lst и применяет тест, чтобы увидеть, есть ли в нем _ или U. Это понимание списка приводит к True/False для каждого элемента в списке. any затем ищет первый True. Если он находит один, он немедленно возвращает True. Если он не находит его, он возвращает False.

EDIT

Хорошо, мы четко переехали на территорию «Просто потому, что вы можете не означает, что вы должны,», но вот решение, которое включает в себя новое условие, введенную в комментариях:

from collections import Counter 
import re 

lists = [['E12.2', 'E16.1', 'E15.1'], 
     ['E10.1', 'I11.2', 'I10.1_27353757'], 
     ['E16.1', 'E18.1', 'E17.3'], 
     ['E1.8', 'I12.1_111682336', 'I12.1_111682195'], 
     ['E55.1', 'E57.1', 'E56.1','E88.1'], 
     ['U22.3', 'U22.6_13735517', 'U23.1'], 
     ['E7.2', 'E9.5', 'E9.3']] 

for lst in lists: 
    if (len(lst) != 3 and not any('_' in item or 'U' in item for item in lst) and 
      (Counter(match.groups(1) for match in [re.match(r'E(\d+)\.', item) for item in lst] if match is not None) 
      .most_common(1) or [(None, 1)])[0][1] == 1): 
     print(lst) 

# Output: 
# ['E55.1', 'E57.1', 'E56.1', 'E88.1'] 

Counter подсчитывает вещи, re.match пытается найти номера после E с, и .most_common(1) or [(None, 1)], чтобы убедиться, что даже если нет подходящих элементов, мы можем по-прежнему индекс в результате и искать наибольшее колич er вхождений.

Хотя предыдущий код был в порядке, это теперь ужасный код, и вместо этого его следует переместить на другую функцию. :-)

+0

Для удовольствия, выражение генератор также может быть заменен на 'карте (набор («U _»). Пересечения, л)' –

+0

привет smarx, Алекс У меня есть еще одну линию, что список, как [ «E7.2» , 'E9.5', 'E9.3'] Я хочу поставить другое условие, когда я не хочу, чтобы что-либо после того, как E было того же числа (в этом случае это E9 в обоих случаях), как удалить такой линии? Одна вещь, о которой я могу думать, разделена, если есть способ включить все в одну строку. – AishwaryaKulkarni

+0

С этой целью E9.3 совпадает с E9.5, но предположительно (из предыдущих примеров), E55.1 не совпадает с E56.1. Это правильно?(Вы интерпретируете его как E, за которым следует десятичное число и игнорируете все после десятичной точки?) – smarx

1

Однострочник:

ls= [['E12.2', 'E16.1', 'E15.1'], 
    ['E10.1', 'I11.2', 'I10.1_27353757'], 
    ['E16.1', 'E18.1', 'E17.3'], 
    ['E1.8', 'I12.1_111682336', 'I12.1_111682195'], 
    ['E55.1', 'E57.1', 'E56.1','E88.1'], 
    ['U22.3', 'U22.6_13735517', 'U23.1']] 

print(list(filter(lambda l : not any(('_' in x or 'U' in x) for x in l),filter(lambda l : len(l)!=3,ls)))) 

результат:

[['E55.1', 'E57.1', 'E56.1', 'E88.1']] 

это комплекс Признаюсь, но отвечает спецификации, так как это один вкладыш:

  • внешняя условие фильтра: отрицание (подчеркивание или U не содержится ни в одном элементе списка).
  • внутренний фильтр состояние: список len! = 3. Лучше начать с этого, чтобы избежать ненужной обработки элементов.
+1

Если вы занимаетесь подобным делом, я считаю, что понимание списка более читаемо. Например, преобразование моего ответа: '[lst для lst в списках, если len (lst)! = 3 и не any ('_' в элементе или 'U' в элементе для элемента в lst)]'. – smarx

+0

это определенно лучше, да. 'filter' потерял свое очарование, когда вам пришлось преобразовать его в' list'. Вы должны добавить это в свой ответ. Я сделаю это. –