簡體   English   中英

用正則表達式過濾字典列表的好方法和pythonic方法

[英]Good and pythonic way to filter list of dictionaries with regular expressions

所以假設我有一個這樣的列表/元組。

dic = ({name: 'Kan',number: '2ABC345', year: '2000'}, 
 {name: 'Jhon',number: '2TTC345', year: '2001'},
 {name: 'Louise',number: '2ABC366', year: '2001'},
 {name: 'Kevin',number: '2ABY000', year: '2002'})

如何在此列表中使用過濾器和正則表達式? 我在想這樣的事情,但我似乎無法更正代碼。

 def func(dic, expression, keysection):
    r = re.compile(dic)
    x = list(filter(lambda x: r.findall(rexpression) in x[keysection], dic))
    print(x)

所以假設我想要 2000 年我會做這樣的事情,

func(dic, 2000, 'year')
>>> [{name: 'Kan',number: '2ABC345', year: 2000}]

或名稱的第一個字母是 ak,

func(dic, '^K', 'name')
>>> [ {name: 'Kan',number: '2ABC345', year: 2000}, {name: 'Kevin',number: '2ABY000', year: 2002}]

或查看數字是否以 2 開頭並有 7 個數字,

func(dic, '2\d{7}', 'number')
>>> [ {name: 'Kan',number: '2ABC345', year: 2000}, {name: 'Jhon',number: '2TTC345', year: 2001},{name: 'Louise',number: '2ABC366', year: 2001}, {name: 'Kevin',number: '2ABY000', year: 2002} ]

問題是,我是正則表達式的新手,我不確定上面的代碼是否正確,以及使用正則表達式過濾器的最佳和最 Python 的方式是什么。

我不會嘗試讓 function 承擔所有這些責任。 這將使測試變得異常困難。 相反,我會為每種情況使用最簡單的列表推導:

import re

dic = (
    {"name": "Kan",    "number": "2ABC345", "year": 2000},
    {"name": "Jhon",   "number": "2TTC345", "year": 2001},
    {"name": "Louise", "number": "2ABC366", "year": 2001},
    {"name": "Kevin",  "number": "2ABY000", "year": 2002},
)


# So let's say I want the year 2000
year_2000 = [d for d in dic if d["year"] == 2000]

# or the first letter in name be a k
name_k = [d for d in dic if d["name"].startswith("K")]

# or to see if the number starts with 2 and has 7 numbers
starts_2_digits_7 = [d for d in dic if re.match(r"^2\d{6}$", d["number"])]

您不需要為它創建 function。 正則表達式必須是可讀的。 Lambda 完成這項工作。

print(list(filter(lambda x: x['year'] == 2000, dic)))

# Output:
[{'name': 'Kan', 'number': '2ABC345', 'year': 2000}]

print(list(filter(lambda x: x['name'][0] == 'K', dic)))

# Output:
[{'name': 'Kan', 'number': '2ABC345', 'year': 2000},
 {'name': 'Kevin', 'number': '2ABY000', 'year': 2002}]

print(list(filter(lambda x: x['number'][0] == '2' and len(x['number']) == 7, dic)))

# Output:
[{'name': 'Kan', 'number': '2ABC345', 'year': 2000},
 {'name': 'Jhon', 'number': '2TTC345', 'year': 2001},
 {'name': 'Louise', 'number': '2ABC366', 'year': 2001},
 {'name': 'Kevin', 'number': '2ABY000', 'year': 2002}]

但我真的建議為此使用 pandas。

讓我們從正則表達式對字符串進行操作的說明開始。 因此,您最好更正您的dic ,以便每個字典都包含字符串(最初年份是一個數字)。

您應該做的第一個更正是re.compile(dic)是錯誤的。 您可以編譯模式,而不是字典。

而且由於您只執行一次模式,因此無需提前編譯它。 僅使用模式參數(字符串)時會更簡單。

您的 function 可以是:

def func(dic, pat, key):
    return list(filter(lambda x: re.search(pat, x[key]), dic))

當您只想打印找到的內容時,function 返回結果就足夠了,當您調用 function 時,結果將被打印出來。

試試func(dic, '2000', 'year')func(dic, '^K', 'name') 它應該打印你想要的。

但是嘗試運行func(dic, '2\d{7}', 'number')將返回[] (一個空列表),因為您的數據樣本中沒有數字包含2后跟 7 位數字。

但是您可以例如運行func(dic, '2A[AZ]{2}', 'number') ,即查找包含以下數字的字典:

  • '2A' ,
  • 然后是2個字母。

這次你會得到:

[{'name': 'Kan', 'number': '2ABC345', 'year': '2000'},
 {'name': 'Louise', 'number': '2ABC366', 'year': '2001'},
 {'name': 'Kevin', 'number': '2ABY000', 'year': '2002'}]

編輯

如果您的字典中有一些字符串以外的元素,您可以將它們轉換為 function 中的字符串。 將您的 function 更改為:

def func(dic, pat, key):
    return list(filter(lambda x: re.search(pat, str(x[key])), dic))

它也適用於源字典中的非字符串元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM