Python:找到所有可能的字符组合与字符序列(分词)
我正在做一些分词实验,如下所示。Python:找到所有可能的字符组合与字符序列(分词)
lst
是一个字符序列,而output
是所有可能的单词。
lst = ['a', 'b', 'c', 'd']
def foo(lst):
...
return output
output = [['a', 'b', 'c', 'd'],
['ab', 'c', 'd'],
['a', 'bc', 'd'],
['a', 'b', 'cd'],
['ab', 'cd'],
['abc', 'd'],
['a', 'bcd'],
['abcd']]
我在itertools
库检查combinations
和permutations
,
也试过combinatorics。
但是,似乎我看着错误的一面,因为这不是纯粹的置换和组合...
看来我可以通过使用大量循环来实现这一点,但效率可能很低。所以像['ba', 'dc']
或['cd', 'ab']
组合是无效的
编辑
词序是很重要的。
从左至右的顺序应始终为。
编辑
@斯图尔特的解决方案并不在Python 2.7.6工作
编辑
@斯图尔特的解决方案确实在Python 2.7.6工作,请参见下面的评论。
itertools.product
的确应该能够帮助你。
这个想法是这样的: - 考虑A1,A2,...,由板块分隔的AN。将会有N-1块平板。 如果有板块存在分段。如果没有平板,则有一个连接。因此,对于给定的长度为N的序列,应该有2 ^(N-1)个这样的组合。
就像下面
import itertools
lst = ['a', 'b', 'c', 'd']
combinatorics = itertools.product([True, False], repeat=len(lst) - 1)
solution = []
for combination in combinatorics:
i = 0
one_such_combination = [lst[i]]
for slab in combination:
i += 1
if not slab: # there is a join
one_such_combination[-1] += lst[i]
else:
one_such_combination += [lst[i]]
solution.append(one_such_combination)
print solution
我选择了这个答案,因为花费最少的时间,但其他的解决方案也有很大的 – amigcamel 2014-12-03 15:02:26
有8个选项,每个镜像二进制数0到7:
000
001
010
011
100
101
110
111
每个0和1代表是否该索引处的2个字母“胶合”在一起。 0表示否,1表示是。
>>> lst = ['a', 'b', 'c', 'd']
... output = []
... formatstr = "{{:0{}.0f}}".format(len(lst)-1)
... for i in range(2**(len(lst)-1)):
... output.append([])
... s = "{:b}".format(i)
... s = str(formatstr.format(float(s)))
... lstcopy = lst[:]
... for j, c in enumerate(s):
... if c == "1":
... lstcopy[j+1] = lstcopy[j] + lstcopy[j+1]
... else:
... output[-1].append(lstcopy[j])
... output[-1].append(lstcopy[-1])
... output
[['a', 'b', 'c', 'd'],
['a', 'b', 'cd'],
['a', 'bc', 'd'],
['a', 'bcd'],
['ab', 'c', 'd'],
['ab', 'cd'],
['abc', 'd'],
['abcd']]
>>>
您的代码isn不为lst = ['a','b','c','d','e']工作。 – 2014-12-03 04:23:36
谢谢!修复它以适用于更多字母的情况。即使我没有得到接受,这是一个有趣的练习:) – twasbrillig 2014-12-03 04:34:04
^哈哈!我赞成你的。我们都有相同的解决方案。你快了! :-) – Sriram 2014-12-03 04:55:52
#!/usr/bin/env python
from itertools import combinations
a = ['a', 'b', 'c', 'd']
a = "".join(a)
cuts = []
for i in range(0,len(a)):
cuts.extend(combinations(range(1,len(a)),i))
for i in cuts:
last = 0
output = []
for j in i:
output.append(a[last:j])
last = j
output.append(a[last:])
print(output)
输出:
zsh 2419 % ./words.py
['abcd']
['a', 'bcd']
['ab', 'cd']
['abc', 'd']
['a', 'b', 'cd']
['a', 'bc', 'd']
['ab', 'c', 'd']
['a', 'b', 'c', 'd']
我不能upvote你。我在你的回答下写下评论的理由。 你的代码我小那么我的,这是很好的,但是,我的机器上的代码不到风度很好地工作:( – 2014-12-03 04:55:16
这实际上是斯图尔特的回答,不是我的,但Sririam upvoted矿山所以这一切都很好。 – twasbrillig 2014-12-03 05:06:14
您可以使用递归发生器:
def split_combinations(L):
for split in range(1, len(L)):
for combination in split_combinations(L[split:]):
yield [L[:split]] + combination
yield [L]
print (list(split_combinations('abcd')))
编辑。我不确定这会如何扩展长字符串,以及它达到Python递归限制的程度。与其他一些答案类似,您也可以使用combinations
从itertools
开始处理每个可能的组合点。
这些似乎都按预期在Python 2.7(see here)和Python 3.2(here)工作。正如@twasbrillig所说,确保你缩进如图所示。
我没有看到![‘ABC’‘d’]在输出 – 2014-12-03 04:28:35
我真的看到它 – twasbrillig 2014-12-03 04:37:22
'在文献[1]:?DEF split_combinations(L) : ...:在范围(,LEN(L)1)拆分: ...:用于组合在split_combinations(L [分裂:]): ...:产率[L [:分割]] +组合 ...:收益率[L] ...: In [2]:print(list(split_combinatio ns('abcd'))) [['a','b','cd'],['a','bcd'],['a','bcd'],['abcd'], ['ab','cd'],['abcd'],['abcd']]' – 2014-12-03 04:41:17
请参阅我的代码在Python 2.7.3中使用[here](http://ideone.com/ufVuEm)和Python 3.2.3中的[here](http://ideone.com/N4y9t7) – Stuart 2014-12-03 10:33:23