【问题标题】:Generate all unique k-subsequences生成所有唯一的 k 子序列
【发布时间】:2020-02-18 21:51:40
【问题描述】:

我正在尝试编写一个 Python(至少在最初)函数来生成某个长度为 k(其中 k > 0)的所有子序列。由于我只需要唯一的子序列,因此我将子序列和部分子序列都存储在 sets 中。以下,改编自同事,是我能想到的最好的。看起来......过于复杂......而且我应该能够滥用itertools 或递归来做我想做的事情。谁能做得更好?

from typing import Set, Tuple


def subsequences(string: str, k: int) -> Set[Tuple[str, ...]]:
    if len(string) < k:
        return set()
    start = tuple(string[:k])
    result = {start}
    prev_state = [start]
    curr_state = set()
    for s in string[k:]:
        for p in prev_state:
            for i in range(k):
                new = p[:i] + p[i + 1 :] + (s,)
                curr_state.add(new)
        result.update(curr_state)
        prev_state = list(curr_state)
        curr_state.clear()
    return result

(对于上下文,我对k-strictly piecewise languages 的归纳感兴趣,它是常规语言的有效可学习子类,并且语法可以用所有合法的 k 子序列来表征。

最终我也在考虑在 C++ 中执行此操作,其中 std::make_tuple 不如 Python tuple 强大。)

【问题讨论】:

  • 你能补充一些例子吗?什么的所有子序列?
  • @DanielMesejo:一些可迭代的所有子序列(这里输入为字符串)。 "foo"的2个子序列是{("f", "o"), ("o", "o")}"foobar"的3个子序列是{('o', 'b', 'r'), ('o', 'o', 'a'), ('f', 'b', 'a'), ('o', 'a', 'r'), ('f', 'o', 'o'), ('f', 'o', 'r'), ('b', 'a', 'r'), ('o', 'b', 'a'), ('f', 'a', 'r'), ('o', 'o', 'r'), ('f', 'b', 'r'), ('o', 'o', 'b'), ('f', 'o', 'b'), ('f', 'o', 'a')}
  • @SyntaxVoid 我想我可以做frozenset(itertools.combinations(string, k)),但我想知道避免中间计算是否有意义。

标签: python itertools formal-languages subsequence


【解决方案1】:

您想要一组来自n 项目的r 组合(无替换,&lt;= (n choose r)

给定

import itertools as it

import more_itertools as mit

代码

选项 1 - itertools.combinations

set(it.combinations("foo", 2))
# {('f', 'o'), ('o', 'o')}

set(it.combinations("foobar", 3))
# {('b', 'a', 'r'),
#  ('f', 'a', 'r'),
#  ('f', 'b', 'a'),
#  ('f', 'b', 'r'),
#  ('f', 'o', 'a'),
#  ('f', 'o', 'b'),
#  ('f', 'o', 'o'),
#  ('f', 'o', 'r'),
#  ('o', 'a', 'r'),
#  ('o', 'b', 'a'),
#  ('o', 'b', 'r'),
#  ('o', 'o', 'a'),
#  ('o', 'o', 'b'),
#  ('o', 'o', 'r')}

选项 2 - more_itertools.distinct_combinations

list(mit.distinct_combinations("foo", 2))
# [('f', 'o'), ('o', 'o')]

list(mit.distinct_combinations("foobar", 3))
# [('f', 'o', 'o'),
#  ('f', 'o', 'b'),
#  ('f', 'o', 'a'),
#  ('f', 'o', 'r'),
#  ('f', 'b', 'a'),
#  ('f', 'b', 'r'),
#  ('f', 'a', 'r'),
#  ('o', 'o', 'b'),
#  ('o', 'o', 'a'),
#  ('o', 'o', 'r'),
#  ('o', 'b', 'a'),
#  ('o', 'b', 'r'),
#  ('o', 'a', 'r'),
#  ('b', 'a', 'r')]

两个选项产生相同的(无序的)输出。然而:

  • 选项 1 采用所有组合(包括重复项)的集合
  • 选项 2 不计算重复的中间体

通过&gt; pip install more_itertools安装more_itertools

另见rough implementationitertools.combinations 书面Python。

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 2012-05-09
    相关资源
    最近更新 更多