【发布时间】:2016-07-22 17:27:20
【问题描述】:
我有一个包含 ~120'000 个不同长度(从 4 到 27)的字符串的列表,我想检查这些字符串是否由字典中存在的子字符串组成,并且这些子字符串可以是各种长度,最少 2 个字符。
例如,一个 9 个字符长的字符串将被分成最少 2 个子字符串。当然我需要所有可能的组合
astring = '123456789'
# possible divisions
2 sub-strings = [['12','3456789'],['1234567','89'],['123','456789'],...]
3 sub-strings = [['12345', '67','89'],['1234','567','89']...]
4 sub-strings = [['12','34','56','789'],['12','34','567','89']...]
我找到了code below at this address,在根据要求拒绝结果后,我得到了我需要的东西,但我不确定它是不是太慢了。在 18 个字符长的字符串中,处理一个字符串需要 2 秒(整个列表需要几个小时)。 如果是 18 个字符长的字符串,我可以从 131072 个中得到 1596 个好的切片,所以 98% 是没用的。 有更快的方法吗?
from itertools import chain, combinations
def partition(iterable, chain=chain, map=map):
s = iterable if hasattr(iterable, '__getslice__') else tuple(iterable)
n = len(s)
first, middle, last = [0], range(1, n), [n]
getslice = s.__getslice__
return [map(getslice, chain(first, div), chain(div, last))
for i in range(n) for div in combinations(middle, i)]
some_string = '12345678'
for xyz in xrange(100):
for x in partition(some_string):
if (any(len(astring) == 1 for astring in x)):
continue
if len(x) == 1:
continue
# otherwise do something here
指定回答 eyquem 评论:
我有一本日语单词词典(日语不使用空格),并且很多长度为 4 个字符或更长的单词是由较短单词组成的复合词。我想过滤掉那些可以拆分成较短单词的单词。稍后我可以查看列表并确保单词切片具有语义意义。
这种方法是一种残酷的力量,我认为它会更简单,我可以使用它来代替更合乎逻辑但更复杂且递归有限的 for 循环。 从左边开始,找到最长的单词...
问候 巴特
【问题讨论】:
-
@tehjoker Code Review 只审查作者自己的代码。
-
在这120'000个字符串中,有多少个子字符串被关注和被搜索?为什么这些子字符串会出现在字典中?它们是字典中的键或值,还是集合中的字典值?
-
Python 2.7.11 文档:
operator.__getslice__(a, b, c):将 a 的切片从索引 b 返回到索引 c-1。 自 2.6 版起已弃用:此函数在 Python 3.x 中已删除。将 getitem() 与切片索引一起使用。 -
感谢 eyquem。与此同时,我编写了一个递归有限的代码,它可以在 0.7 秒内快速运行 70'000 个条目,但它需要 80 行,所以绝对不优雅。使用对整数进行分区但跳过包含 1 的结果并从最少整数到最多生成结果的生成器,getslice(a, b, c) 会好得多。我不确定是否应该在此处发布代码,因为它不能完全回答问题?