【问题标题】:How to break early from a cartesian product recursive function once a solution is found?一旦找到解决方案,如何尽早脱离笛卡尔积递归函数?
【发布时间】:2020-09-13 09:59:33
【问题描述】:

我正在分析单词的语音组成,作为其中的一部分,我一直在使用笛卡尔积来匹配给定单词的拼写排列。一个单词中的每个声音都可以用几个拼写来表示,程序会为单词中的每个声音确定正确的拼写。列表的数量未知,长度未知。

我目前是列表理解中的用户 itertools 的 product(),即暴力破解,在返回值之前检查每个排列。这是 Python 3 中的相关部分:

from itertools import product


def cartesian_match(string, iterables):
    """Gets the phonetic spelling breakdown of a word via cartesian product.

    Args:
        string (str):     String for which a matched spelling is wanted.
        iterables (list): A list of lists of unknown number and length.
                          Each sublist contains only str elements.
                          Each sublist contains all possible spellings of a
                          phoneme.

    Returns:
        list: the first matched list of spelling units.

    Example (simplified):
      Args:
        string = "python"
        iterables = [
          'p', 'pp'],['i', 'ie', 'y', 'igh'],['th'],['or', 'ou', 'e', 'o'],[
          'nd', 'nn', 'n', 'ne']

      Returns:
        ['p', 'y', 'th', 'o', 'n']

    """
    return [x for x in product(*iterables) if "".join(x) == string][0]

对于复杂的单词,笛卡尔积很大,有几千万的排列。有些单词的计算时间超过 15 分钟。我有数千个单词要分析,所以速度目前是个问题。

为了加快速度,我需要一个在发现值后立即返回值的函数,而不是形成一个笛卡尔积并且必须遍历每一个排列。它还可以让我优化每个子列表中的元素序列,以便更快地获得匹配的值。

我的挑战是,我无法弄清楚如何用未知数量的未知长度列表迭代地执行此操作,而且我在任何尝试及早突破递归函数时都失败了。

谁能指出我正确的方向?

【问题讨论】:

  • 为了帮助我们回答你,你能举一个有问题的输入和想要的输出的例子吗?就我个人而言,我不确定你想在哪里打破循环。
  • 我已尽我所能在文档字符串示例中说明这一点。例如,笛卡尔积中有 2*4*1*4*4 = 128 个排列。这只是说明性的,实际上每个单词都有数十万或数百万个排列。我希望函数在匹配后立即停止并返回值 ['p', 'y', 'th', 'o', 'n'] ,而不是分析每个排列然后返回值.这说明清楚了吗?

标签: python python-3.x recursion itertools cartesian-product


【解决方案1】:
for x in in product(*iterables):
    if "".join(x) == string:
        return x

顺便说一句:您的函数不是递归的 - 这个问题的标题具有误导性。

【讨论】:

  • 这是笛卡尔积本身的形成,即 product(*iterables),我认为它占用了大部分计算时间,而不是匹配部分。因此,我一直试图摆脱对 product() 的依赖。不过,您是对的,这确实有助于匹配部分。注意:标题中的递归是指 product() 方法的内部,我将尝试澄清我的帖子。
  • 不。 product 是一个生成器,它不会创建一个完整的结果列表,而是根据需要一个一个地返回它们。只需使用timeit 测量即可。
  • 是的,你是对的。快多了。不敢相信我没想过早点尝试。感谢您让我正确!
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 2018-09-28
  • 2022-07-12
  • 2021-11-06
相关资源
最近更新 更多