【问题标题】:Subwords of a string in PythonPython中字符串的子词
【发布时间】:2022-01-03 15:46:34
【问题描述】:

我正在尝试快速创建字符串的每个可能版本的列表。我并不是特别指子词 - 例如来自字符串 "ABC",我想得到:

['C', 'B', 'BC', 'A', 'AB', 'ABC']
(没有 "AC" 这是一个子词)

“123”也是如此:
我想得到 ['3', '2', '23', '1', '12', '123'] 而不是 ['3', '2', '23', '1', '13', '12', '123']

【问题讨论】:

  • 更清楚地定义subwords 的含义,而不是仅仅举例。人们。可以根据他们的理解解释不同的定义。
  • 所以你只是不想element[0]+element[-1] 出现在最终列表中,还是什么?根据您自己的研究,到目前为止您尝试过什么?你的尝试出了什么问题?请edit 包含minimal reproducible examplecode
  • itertools 将是一个很好的起点
  • list(set(str[i:j] for i in range(0, len(str)) for j in range(i+1, len(str)+1)))
  • 最常用的术语是 substringsubsequence,其中 substring 是您想要的,即子串 = 连续的子序列。另见:Difference : subsequences and substrings?

标签: python algorithm recursion substring slice


【解决方案1】:

这是一个简单的基于循环和切片的生成器函数:

def subs(s):
    for i in range(len(s)):
        for j in range(i+1, len(s)+1):
            yield s[i:j]

>>> list(subs("ABC"))
['A', 'AB', 'ABC', 'B', 'BC', 'C']

【讨论】:

  • 在“香蕉”上试试这个。 (或者更简单的“aaaa”。)这是想要的结果吗? (也许,但似乎不太可能。)
  • 是的,这是我想要的结果,但是,我正在寻找不会占用太多内存空间的最快方法。对于像 "z"*100000 这样的字符串,它占用了太多空间——我需要它占用更少的内存。
  • @trab:你为什么要重复?如果您确实需要它们,您应该编辑您的问题。如果您不想要它们,请尝试我评论中的简单表达。
  • 这非常节省空间。只是不要将字符串放在列表中,只需在迭代生成器对象时对其进行处理。
【解决方案2】:

可能会更快地扩展子字符串而不是新切片每个:

def subs(s):
    while s:
        t = ''
        for c in s:
            t += c
            yield t
        s = s[1:]

s = "z" * 5000 的基准测试结果:

8.4 seconds  subs_slice
1.5 seconds  subs_extend

基准代码 (Try it online!):

from timeit import timeit
from collections import deque

def subs_slice(s):
    for i in range(len(s)):
        for j in range(i+1, len(s)+1):
            yield s[i:j]

def subs_extend(s):
    while s:
        t = ''
        for c in s:
            t += c
            yield t
        s = s[1:]

funcs = subs_slice, subs_extend

for func in funcs:
    print(list(func('ABCD')))

s = "z" * 5000
for _ in range(3):
    for func in funcs:
        t = timeit(lambda: deque(func(s), 0), number=1)
        print(t, func.__name__)
    print()

【讨论】:

    【解决方案3】:

    对于ABC,您只需获取['C', 'B', 'BC', 'A', 'AB', 'ABC', 'AC'],然后使用remove() 从列表中删除子词。 E.i:

    abc_list = ['C', 'B', 'BC', 'A', 'AB', 'ABC', 'AC']
    abc_list.remove('AC')
    

    输出:['C', 'B', 'BC', 'A', 'AB', 'ABC']

    该问题缺乏上下文,无法为您提供完整答案。您的所有字符串都包含 3 个或更多字符吗?你如何定义你不需要的东西? 如果所有的字符串都是 3 个字符的长度,那么你可以使用这个:

    def subwording(word: str):
        subword = word[0]+word[2]
        return subword
    

    然后你可以从你的列表中删除subword

    【讨论】:

    • n字符的字符串中,有n(n+1)/2子字符串和2**n子序列。以n=30 为例,这是435 子字符串和1,073,741,824 子序列。您建议首先生成所有子序列,然后删除不连续的子序列。那将是非常低效的。
    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2014-05-20
    • 1970-01-01
    • 2016-03-10
    • 2021-11-23
    • 2014-03-15
    • 2011-07-06
    • 2021-08-25
    相关资源
    最近更新 更多