【问题标题】:A better way than looping and calling functions that loop and call another functions比循环和调用循环和调用另一个函数的函数更好的方法
【发布时间】:2018-07-31 12:03:42
【问题描述】:

我有一个 message(字符串),它由 transactions 组成,它由 groups 组成,而elements。

我有比 循环和调用函数循环和调用另一个函数循环和调用另一个函数更好的方法来解析此类消息因为我发现以下内容很愚蠢:

class Parser:
  def parse_msg(self, msg):
    trans = re.findall(trans_pattern, msg)
    for t in trans:
      self.parse_trans(t)

  def parse_trans(self, trans):
    groups = re.findall(groups_pattern, trans)
    for g in groups:
      self.parse_group(g)

  def parse_group(self, group):
    elements = re.findall(element_pattern, group)
    for e in elements:
      self.parse_element(e)

  def parse_element(self, e):
    pass

有没有更好的方法/设计模式可以解决这个问题?

【问题讨论】:

  • 如果它是一个指定的语法,你可以为它写一个解析器,例如使用pypi.org/project/pyparsing
  • @deceze 不,这不是语法,而是使用一些预定义标准的基于业务的解析器。
  • 什么?您正在尝试从字符串中获取信息,该字符串可能使用已定义的结构(否则,祝您好运从中获取任何信息),因此您可以在 pyparsing 之类的解析器中定义该结构(语法)。
  • @deceze 抱歉,我误解了您的评论,快速浏览 PyParsing 我认为这无济于事,但我肯定会更仔细地检查它。非常感谢。
  • 还有另一种解析方式——类似于 xml 的 SAX 解析。您可以制作标记器,然后根据所遇到的标记调用函数的处理器。您需要将解析上下文保存在每个令牌函数可用的地方。如果你喜欢 FSM 的东西,它会更有效,但如果你应该完全解析消息,它的代码会更复杂。

标签: python python-3.x algorithm oop design-patterns


【解决方案1】:

嗯,我想有几种可能性。你可以有一些类似下面的结构:

import re

GRAMMAR = (
    trans_pattern, (
        groups_pattern, (
            element_pattern, None
        )
    )
)

def parse_message(msg):
    parse_message_rec(msg, GRAMMAR)

def parse_message_rec(msg, grammar):
    if grammar is None:
        # Leaf element
        return
    pattern, next_grammar = grammar
    children = re.findall(pattern, msg)
    for child in children:
        parse_message_rec(child, next_grammar)

【讨论】:

  • 只是我还是这只是一种奇特的方式来做他已经在做的事情?
  • @CodeMonkey 是的,就是这样。我的理解是 OP 想要一些代码来执行相同的任务,代码冗余更少(并且可能更具可扩展性/可维护性)。
  • 我的印象是 OP 正在寻找优化,这样计算成本就不会那么高了。简而言之,您仍在循环和调用函数,但使用相同的函数而不是多个函数递归地执行它。
  • @CodeMonkey 是的,我知道我的答案的计算成本是相同的。正如我所说,我试图解决的是几乎相同的函数和循环的复制。但问题可能是针对性能而不是代码质量(在这种情况下,需要采用截然不同的方法来改进它,例如使用 cmets 中提出的语法解析器)。
【解决方案2】:

这种方法听起来确实很费力,因为每一位文本都会被重复多次。 O(n^3) 复杂度之类的。

相反,我会创建一个函数来处理一次输入并一次性解析所有内容。为此,听起来您可以使用一个方便的 pyparsing 模块(我自己从未使用过它,所以我不确定学习曲线、难度或优化)。否则,要手动执行此操作,您必须跟踪当前的“深度”(trans、group 或 element),并确定您是在该深度关闭还是打开 trans/group/element,同时跟踪开始和结束表达式之间的数据。简而言之,不要查找所有“反式”,只需找到第一个开始的位置,抓取任何唯一数据直到下一组开始,开始新组,抓取唯一数据直到元素开始,开始新元素,抓取数据直到它关闭,看看是否有另一个元素或者组是否关闭等等。不是那么简洁,但肯定更快。如果速度不是问题,那么您的方法很好。如果它是(或将是)一个问题,那么您将希望一次性解析它。

【讨论】:

    【解决方案3】:

    我命令您使用以下方法:将您的特殊格式转换为简单的 XML(使用正则表达式或您喜欢的),然后您可以应用任何 XML 模式/方法/库来解析您的文本。

    【讨论】:

    • 将其转换为 XML 只会使他的努力加倍。他仍然必须以当前格式对其进行解析才能解决最初的问题。
    猜你喜欢
    • 2018-01-08
    • 2023-02-06
    • 2022-01-20
    • 1970-01-01
    • 2014-08-27
    • 2020-03-13
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多