簡體   English   中英

使用Python正則表達式從字符串中提取十進制數字

[英]Extracting decimal numbers from string with Python regex

我嘗試使用Python的re庫進行此操作。 從文件中,我得到幾行包含用豎線('|')分隔的元素的行。 我將它們放在列表中,而我需要輸入的數字才能與它們一起使用。

這將是我要拆分的字符串之一:

>>print(line_input)
>>[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]

我的意圖是用方括號之間的每個元素形成一個向量。

我創建了這個正則表達式

>>test_pattern="\|\[(\d*(\.\d+)?), (\d*(\.\d+)?), (\d*(\.\d+)?)]"

但是結果有點令人困惑。 特別是,結果是

>>vectors = re.findall(test_pattern, line_input)

>>print(vectors)
>>[('240', '', '7821', '', '0', '', '12', '', '605', '', '0', '', '3', ''), ('1.5', '.5', '7881.25', '.25', '0', '', '0', '', '0', '', '0', '', '0', ''), ('23437', '', '76611', '', '0', '', '0', '', '0', '', '605', '', '605', '')]

我不知道空格是從哪里來的,也不知道為什么小數部分會重復。 我知道我幾乎明白了,至少,我確定這是一個很小的簡單細節,但我沒有。

提前非常感謝您。

這些空格是可能的空小數。 vectors變量包含所有捕獲組,無論是否為空。 因此,當有一個小數時,您會得到一個外部組(\\d*(\\.\\d+)?)匹配項,而一個是內部組(\\.\\d+)?匹配項(\\.\\d+)? 將內部設為非捕獲組:

(\\d+(?:\\.\\d+)?)

注意:我還更改了它,要求小數點前有一個數字(如果有)。

這樣做的另一種方法(如果輸入格式不同,則可能不是很健壯)是將字符串拆分為[] | []以獲取列表,然后拆分為','以獲取值:

from decimal import Decimal
input_str = '[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]'

# ignore the first and last '[' and ']' chars, then split on list separators
list_strs = input_str[1:-1].split(']|[')

# Split on ', ' to get individual decimal values
int_lists = [[Decimal(i) for i in s.split(', ')] for s in list_strs]

# int_lists contains a list of lists of decimal values, like the input format

for l in int_lists:
    print(', '.join(str(d) for d in l))

結果

240, 7821, 0, 12, 605, 0, 3
1.5, 7881.25, 0, 543, 876, 0, 121
237, 761, 0, 61, 7, 605, 605

正則表達式有它的位置。 但是,用pyparsing編寫的語法通常更易於編寫和閱讀。

>>> import pyparsing as pp

數字就像是由數字和句點/句號組成的單詞。 它們后面可以有逗號,我們可以簡單地取消它們。

>>> number = pp.Word(pp.nums+'.') + pp.Optional(',').suppress()

列表之一包括一個左方括號(我們將其取消顯示),一個或多個數字(如剛剛定義的),一個右方括號(我們也將其刪除)以及一個可選的直角字符(再次被抑制)組成。 (順便說一句,此欄在某種程度上是多余的,因為右括號將列表關閉了。)

我們將Group應用於整個構造,以便pyparsing將我們未壓縮的項目組織到單獨的Python列表中。

>>> one_list = pp.Group(pp.Suppress('[') + pp.OneOrMore(number) + pp.Suppress(']') + pp.Suppress(pp.Optional('|')))

列表的整個集合只是一個或多個列表。

>>> whole = pp.OneOrMore(one_list)

這是輸入

>>> line_input = '[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]'

...我們將其解析為結果r

>>> r = whole.parseString(line_input)

我們可以顯示結果列表。

>>> r[0]
(['240', '7821', '0', '12', '605', '0', '3'], {})
>>> r[1]
(['1.5', '7881.25', '0', '543', '876', '0', '121'], {})
>>> r[2]
(['237', '761', '0', '61', '7', '605', '605'], {})

我們更希望將數字作為數字。 在這種情況下,我們知道列表中的字符串代表浮點數或整數。

>>> for l in r.asList():
...     [int(_) if _.isnumeric() else float(_) for _ in l]
... 
[240, 7821, 0, 12, 605, 0, 3]
[1.5, 7881.25, 0, 543, 876, 0, 121]
[237, 761, 0, 61, 7, 605, 605]

您可以嘗試以下方法:

import re
s = "[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]" 
data = re.findall("\d+\.*\d+", s)

輸出:

['240', '7821', '12', '605', '1.5', '7881.25', '543', '876', '121', '237', '761', '61', '605', '605']

暫無
暫無

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

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