Stories

Detail Return Return

用 pyparsing 3.x 化簡括號冗餘的或非邏輯表達式(qbit) - Stories Detail

前言

  • 技術棧
Python    3.11
pyparsing 3.1.2

案例

  • 測試代碼
# encoding: utf-8
# author: qbit
# date: 2024-04-23
# summary: 化簡括號冗餘的與或非邏輯表達式

import pyparsing as pp

line = '(((owner=111 AND doc_type=222))) OR author=333 OR organ=444 AND ((NOT pub_year>555))'

operator = (
            pp.Literal(r'=') |
            pp.Literal(r'>')
        )
field = pp.Word(pp.alphanums + '_')
value = pp.Word(pp.alphanums)
exprGroup: pp.Group = pp.Group(field("field") + operator("operator") + value("value"))
logicAND = pp.Word('AND')('logic')
logicOR = pp.Word('OR')('logic')
logicNOT = pp.Word('NOT')('logic')

exprForward = pp.infixNotation(
    exprGroup("Expr"),
    [
        (logicAND, 2, pp.opAssoc.LEFT, ),    # 第二個參數為操作數的個數,並不是結合優先級
        (logicOR, 2, pp.opAssoc.LEFT, ),
        (logicNOT, 1, pp.opAssoc.RIGHT, ),
    ]
).setResultsName("Result", True)

result: pp.results.ParseResults = exprForward.parseString(line, parseAll=True)

def list2qs(lst):
    if (len(lst) == 1) and isinstance(lst[0], list):            # 列表中只有一個列表元素
        return list2qs(lst[0])
    
    if lst[0] == 'NOT':
        return f"(NOT {list2qs(lst[1])})"
    
    if lst[1] == 'AND':
        return ' AND '.join( [list2qs(x) for x in lst[0::2]])   # 步長為2取數據

    if lst[1] == 'OR':
        return ' OR '.join( [list2qs(x) for x in lst[0::2]])    # 步長為2取數據
    
    match lst[1]:
        case r'=':
            return f"{lst[0]}={lst[2]}"
        case r'>':
            return f"{lst[0]}>{lst[2]}"
        case _:
            pass

qs = list2qs(result.as_list())
print(f"冗餘表達式: {line}")
print(f"簡化表達式: {qs}")
  • 測試輸出
冗餘表達式: (((owner=111 AND doc_type=222))) OR author=333 OR organ=444 AND ((NOT pub_year>555))
簡化表達式: owner=111 AND doc_type=222 OR author=333 OR organ=444 AND (NOT pub_year>555)

相關資料

  • https://pypi.org/project/pyparsing/
  • https://pypi.org/project/boolean-parser
  • https://pypi.org/project/parsimonious/
  • https://pypi.org/project/sympy/

文章

  • PyParsing 官方文檔:https://pyparsing-docs.readthedocs.io/en/latest/
  • pyparsing 學習(博客園)
  • 取代正則-使用pyparsing來定製自己的解析器(知乎)
  • Pyparsing快速構建解釋器 | 實戰搜索查詢語法(知乎)
  • parsing logical expression with pyparsing
  • Pyparsing實戰(知乎)
  • 用 pyparsing 3.x 將與或非邏輯表達式轉換為Elasticsearch查詢語句
本文出自 qbit snap
user avatar u_17037082 Avatar linybjikezhilu Avatar lizhuo6 Avatar u_17467352 Avatar _607c00baa52ff Avatar anjingdexiaoyanyao_ciaxxr Avatar 2763926672 Avatar
Favorites 7 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.