2016-10-23 42 views
1

我有以下列表條件statment:關於各種正則表達式和Python的list的長度

['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 b中的列表)不包含'_'c)不包含字母'U' 我想在一行中實現,我該怎麼做?我有以下條件工作,我知道你可以使用正則表達式模塊匹配列表中的正則表達式,但我可以做單行的所有條件?

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。爲了分解它,這遍歷每個itemlst並且應用測試以查看_U是否在其中。對於列表中的每個項目,該列表理解導致True/Falseany然後查找第一個True。如果找到,它立即返回True。如果沒有找到,則返回False

編輯

好了,我們已經清楚地搬進了「就因爲你可以並不意味着你應該」,領土,但這裏的是集成在評論中引入的新條件的方案:

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 s中數字和.most_common(1) or [(None, 1)]是確保即使沒有匹配的元素,我們仍然可以索引到結果,並尋找最偉大的麻木呃出現。

雖然前面的代碼沒問題,但現在這是糟糕的代碼,應該將其移出到另一個函數。 :-)

+0

爲了好玩,發生器表達式也可以用'map(set('U _')。intersection,l)' –

+0

hi smarx,alex替換我有另外一行表示['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

如果你遇到這種情況,我認爲列表理解更具可讀性。例如,將我的答案轉換爲:'[如果len(lst)!= 3並且不是任何('_'在項目中或'U'在項目中在lst中]],則首先列出列表。 – smarx

+0

絕對更好,是的。當你不得不將它轉換爲list時,過濾器就失去了魅力。您應該將此添加到_your_答案。我會做的。 –