You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python 3中将含逻辑运算符的查询字符串转为字典或JSON对象

How to Convert a Query String with Logical Operators to a Structured Dictionary in Python 3

Got it, let's tackle this problem. You want to turn a human-readable logical query string like ((blue AND green) OR (brown AND green) OR green) AND NOT red into that nested dictionary/JSON structure you provided. Here's a step-by-step solution with code that handles this parsing and conversion smoothly.

Core Approach

First, let's outline the key steps we'll take:

  • Clean up the input string to standardize formatting and operator casing
  • Recursively parse the expression (since logical queries are inherently nested)
    • Prioritize handling nested parentheses first
    • Split expressions by top-level operators (AND/OR/NOT) that aren't trapped inside parentheses
    • Build the required dictionary structure as we parse each segment

Full Python Implementation

import re
import json

def preprocess_query(query):
    # Remove extra whitespace and standardize operators to lowercase
    cleaned = re.sub(r'\s+', ' ', query.strip())
    cleaned = re.sub(r'\bAND\b', 'and', cleaned)
    cleaned = re.sub(r'\bOR\b', 'or', cleaned)
    cleaned = re.sub(r'\bNOT\b', 'not', cleaned)
    return cleaned

def parse_query(query):
    query = preprocess_query(query)
    
    # Helper to find top-level operators (not enclosed in parentheses)
    def find_top_operator(s):
        paren_count = 0
        for i, char in enumerate(s):
            if char == '(':
                paren_count += 1
            elif char == ')':
                paren_count -= 1
            elif paren_count == 0 and char == ' ':
                # Check if this space precedes a valid operator
                if s[i+1:i+4] in ['and', 'not'] or s[i+1:i+3] == 'or':
                    operator_len = 4 if s[i+1:i+4] in ['and', 'not'] else 3
                    operator_end = i + operator_len
                    # Ensure it's a standalone operator (not part of a word)
                    if operator_end <= len(s) and s[operator_end:operator_end+1] in [' ', ')']:
                        return (s[i+1:operator_end], i)
        return (None, -1)
    
    # Helper to strip redundant outer parentheses
    def strip_outer_parens(s):
        if s.startswith('(') and s.endswith(')'):
            paren_count = 0
            for i, char in enumerate(s):
                if char == '(':
                    paren_count += 1
                elif char == ')':
                    paren_count -= 1
                    if paren_count == 0 and i == len(s)-1:
                        return s[1:-1]
        return s
    
    query = strip_outer_parens(query)
    
    # Handle NOT operator first (highest precedence after parentheses)
    if query.startswith('not '):
        term = query[4:].strip()
        return {
            "operator": "not",
            "filters": [parse_query(term)]
        }
    
    # Find and split on top-level AND/OR
    operator, split_idx = find_top_operator(query)
    if operator:
        left_segment = query[:split_idx].strip()
        right_segment = query[split_idx + len(operator) + 1:].strip()
        # Parse both segments recursively
        left_filter = parse_query(left_segment)
        right_filter = parse_query(right_segment)
        # Build the operator structure
        return {
            "operator": operator,
            "filters": [left_filter, right_filter]
        }
    else:
        # Single term, return base filter structure
        return {
            "means": "contains",
            "value": query.strip()
        }

# Test with your example query
query_str = "((blue AND green) OR (brown AND green) OR green) AND NOT red"
result = {"filter": parse_query(query_str)}

# Print formatted JSON output
print(json.dumps(result, indent=2))

What This Code Does

Let's break down the key parts:

  1. Preprocessing: Cleans up messy whitespace and converts all operators to lowercase to avoid case sensitivity issues.
  2. Parentheses Handling: Removes unnecessary outer parentheses to simplify parsing nested expressions.
  3. Top-level Operator Detection: Scans the string to find operators that aren't inside parentheses—this ensures we parse the expression in the correct order of operations.
  4. Recursive Parsing:
    • For NOT clauses, wraps the parsed term in a "not" operator structure.
    • For AND/OR clauses, splits the query, parses each side, and combines them into the required nested structure.
    • For single keywords, returns the base {"means": "contains", "value": "..."} filter.

Sample Output

Running the code with your example query will produce this structured JSON (matching your requested format):

{
  "filter": {
    "operator": "and",
    "filters": [
      {
        "operator": "or",
        "filters": [
          {
            "operator": "and",
            "filters": [
              {
                "means": "contains",
                "value": "blue"
              },
              {
                "means": "contains",
                "value": "green"
              }
            ]
          },
          {
            "operator": "and",
            "filters": [
              {
                "means": "contains",
                "value": "brown"
              },
              {
                "means": "contains",
                "value": "green"
              }
            ]
          },
          {
            "means": "contains",
            "value": "green"
          }
        ]
      },
      {
        "operator": "not",
        "filters": [
          {
            "means": "contains",
            "value": "red"
          }
        ]
      }
    ]
  }
}

You can extend this code easily—for example, adding support for different means values (like "equals" instead of "contains") by modifying the base case in the parse_query function.

内容的提问来源于stack exchange,提问作者Droid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:55:44