由於您引用了一些測試,這聽起來像您至少已經採取了刺探問題。我假設你已經定義的單號,可以是整數或實 - 不要緊,要轉換的一切反正浮動 - 和兩個數字的一小部分,大概是這樣的:
from pyparsing import Regex, Optional
number = Regex(r"\d+(\.\d*)?").setParseAction(lambda t: float(t[0]))
fraction = number("numerator") + "/" + number("denominator")
fraction.setParseAction(lambda t: t.numerator/t.denominator)
(注意使用解析動作,也做浮點轉換和分數劃分權在分析時的,我更喜歡這樣做,而解析,當我知道東西是不是數字或分數或什麼的,而不是稍後再回來並通過了一堆零散的字符串篩選,試圖重新解析器已經做好了識別邏輯。)
下面是測試情況下,我的COM提出您的問題,由一個整數,分數和整數和分數,同時使用整數和實數:
tests = """\
1
1.0
1/2
1.0/2.0
1 1/2
1.0 1/2
1.0 1.0/2.0""".splitlines()
for t in tests:
print t, fractExpr.parseString(t)
的最後一步是如何定義的分數表達,可以是單個數字,分數,或單個數字和分數。
由於pyparsing是左到右,它不會做同一種回溯喜歡使用regexen做的。所以這個表達式不會工作這麼好:
fractExpr = Optional(number) + Optional(fraction)
綜上所述可能來自數和小數部分的數值加在一起,添加此解析動作:
fractExpr.setParseAction(lambda t: sum(t))
我們的測試結果打印出來:
1 [1.0]
1.0 [1.0]
1/2 [1.0]
1.0/2.0 [1.0]
1 1/2 [1.5]
1.0 1/2 [1.5]
1.0 1.0/2.0 [1.5]
測試用例1/2
,只包含本身的一小部分,領先的分子的Optional(number)
項匹配,但留給我們只是用「/ 2」,W HICH 不匹配Optional(fraction)
- 幸運的是,因爲第二項是可選的,這個「通行證」,但它不是真正做我們想要的。
我們需要fractExpr聰明一點,有它首先尋找一個孤獨的分數,因爲有一個唯一的號碼和分數的領先分子之間的這種潛在的混亂。要做到這一點最簡單的方法就是讓fractExpr閱讀:
fractExpr = fraction | number + Optional(fraction)
現在有了這個變化,我們的測試中走出來更好:
1 [1.0]
1.0 [1.0]
1/2 [0.5]
1.0/2.0 [0.5]
1 1/2 [1.5]
1.0 1/2 [1.5]
1.0 1.0/2.0 [1.5]
有幾個經典的陷阱與pyparsing的,這是其中之一。只要記住,pyparsing只會做你告訴它的前瞻,否則它只是直接從左到右的解析。
真棒,很好的答案,謝謝你花時間拼出來!我們得到了測試用例:1/2 [1.0],並且爲什麼我們一直得到1而不是0.5。它看起來像你勾畫了我們的絆腳石。數據本身非常混亂,但看起來這至少可以爲我們打下堅實的基礎,並列舉其他最常見的客戶產品屬性值表達式。 :) – Xavian 2010-10-12 19:28:29