這可能與Python 3.3: Split string and create all組合等類似問題密切相關,但我無法從中推斷出 Pythonic 解決方案。
問題是:
讓有一個 str ,例如'hi|guys|whats|app',我需要通過分隔符分割該 str 的所有排列。例子:
#splitting only once
['hi','guys|whats|app']
['hi|guys','whats|app']
['hi|guys|whats','app']
#splitting only twice
['hi','guys','whats|app']
['hi','guys|whats','app']
#splitting only three times
...
etc
我可以撰寫一個回溯演算法,但是python(例如itertools)是否提供了一個簡化這個演算法的庫?
提前致謝!!
uj5u.com熱心網友回復:
一種方法是,一旦您拆分了字串,就可以使用itertools.combinations定義串列中的拆分點,其他位置應再次融合。
def lst_merge(lst, positions, sep='|'):
'''merges a list on points other than positions'''
'''A, B, C, D and 0, 1 -> A, B, C|D'''
a = -1
out = []
for b in list(positions) [len(lst)-1]:
out.append('|'.join(lst[a 1:b 1]))
a = b
return out
def split_comb(s, split=1, sep='|'):
from itertools import combinations
l = s.split(sep)
return [lst_merge(l, pos, sep=sep)
for pos in combinations(range(len(l)-1), split)]
例子
>>> split_comb('hi|guys|whats|app', 0)
[['hi|guys|whats|app']]
>>> split_comb('hi|guys|whats|app', 1)
[['hi', 'guys|whats|app'],
['hi|guys', 'whats|app'],
['hi|guys|whats', 'app']]
>>> split_comb('hi|guys|whats|app', 2)
[['hi', 'guys', 'whats|app'],
['hi', 'guys|whats', 'app'],
['hi|guys', 'whats', 'app']]
>>> split_comb('hi|guys|whats|app', 3)
[['hi', 'guys', 'whats', 'app']]
>>> split_comb('hi|guys|whats|app', 4)
[] ## impossible
理由
ABCD -> A B C D
0 1 2
combinations of split points: 0/1 or 0/2 or 1/2
0/1 -> merge on 2 -> A B CD
0/2 -> merge on 1 -> A BC D
1/2 -> merge on 0 -> AB C D
通用函式
這是一個通用版本,像上面一樣作業,但也-1作為引數 for split,在這種情況下它將輸出所有組合
def lst_merge(lst, positions, sep='|'):
a = -1
out = []
for b in list(positions) [len(lst)-1]:
out.append('|'.join(lst[a 1:b 1]))
a = b
return out
def split_comb(s, split=1, sep='|'):
from itertools import combinations, chain
l = s.split(sep)
if split == -1:
pos = chain.from_iterable(combinations(range(len(l)-1), r)
for r in range(len(l) 1))
else:
pos = combinations(range(len(l)-1), split)
return [lst_merge(l, pos, sep=sep)
for pos in pos]
例子:
>>> split_comb('hi|guys|whats|app', -1)
[['hi|guys|whats|app'],
['hi', 'guys|whats|app'],
['hi|guys', 'whats|app'],
['hi|guys|whats', 'app'],
['hi', 'guys', 'whats|app'],
['hi', 'guys|whats', 'app'],
['hi|guys', 'whats', 'app'],
['hi', 'guys', 'whats', 'app']]
uj5u.com熱心網友回復:
這是我想出的遞回函式:
def splitperms(string, i=0):
if len(string) == i:
return [[string]]
elif string[i] == "|":
return [*[[string[:i]] split for split in splitperms(string[i 1:])], *splitperms(string, i 1)]
else:
return splitperms(string, i 1)
輸出:
>>> splitperms('hi|guys|whats|app')
[['hi', 'guys', 'whats', 'app'], ['hi', 'guys', 'whats|app'], ['hi', 'guys|whats', 'app'], ['hi', 'guys|whats|app'], ['hi|guys', 'whats', 'app'], ['hi|guys', 'whats|app'], ['hi|guys|whats', 'app'], ['hi|guys|whats|app']]
>>>
uj5u.com熱心網友回復:
一種使用combinations和的方法chain
from itertools import combinations, chain
def partition(alist, indices):
# https://stackoverflow.com/a/1198876/4001592
pairs = zip(chain([0], indices), chain(indices, [None]))
return (alist[i:j] for i, j in pairs)
s = 'hi|guys|whats|app'
delimiter_count = s.count("|")
splits = s.split("|")
for i in range(1, delimiter_count 1):
print("split", i)
for combination in combinations(range(1, delimiter_count 1), i):
res = ["|".join(part) for part in partition(splits, combination)]
print(res)
輸出
split 1
['hi', 'guys|whats|app']
['hi|guys', 'whats|app']
['hi|guys|whats', 'app']
split 2
['hi', 'guys', 'whats|app']
['hi', 'guys|whats', 'app']
['hi|guys', 'whats', 'app']
split 3
['hi', 'guys', 'whats', 'app']
這個想法是生成所有方式來選擇(或洗掉)分隔符 1、2、3 次并從那里生成磁區。
uj5u.com熱心網友回復:
您可以找到indexall '|'then in all 組合替換'|'為','then split base,','如下所示:
>>> from itertools import combinations
>>> st = 'hi|guys|whats|app'
>>> idxs_rep = [idx for idx, s in enumerate(st) if s=='|']
>>> def combs(x):
... return [c for i in range(len(x) 1) for c in combinations(x,i)]
>>> for idxs in combs(idxs_rep):
... lst_st = list(st)
... for idx in idxs:
... lst_st[idx] = ','
... st2 = ''.join(lst_st)
... print(st2.split(','))
['hi|guys|whats|app']
['hi', 'guys|whats|app']
['hi|guys', 'whats|app']
['hi|guys|whats', 'app']
['hi', 'guys', 'whats|app']
['hi', 'guys|whats', 'app']
['hi|guys', 'whats', 'app']
['hi', 'guys', 'whats', 'app']
uj5u.com熱心網友回復:
如果您想要所有磁區,請嘗試partitions使用more-itertools:
from more_itertools import partitions
s = 'hi|guys|whats|app'
for p in partitions(s.split('|')):
print(list(map('|'.join, p)))
輸出:
['hi|guys|whats|app']
['hi', 'guys|whats|app']
['hi|guys', 'whats|app']
['hi|guys|whats', 'app']
['hi', 'guys', 'whats|app']
['hi', 'guys|whats', 'app']
['hi|guys', 'whats', 'app']
['hi', 'guys', 'whats', 'app']
如果您只想要一定數量的拆分,那么您無需在所有分隔符處拆分然后重新連接各部分,而只需獲取分隔符索引的組合并相應地獲取子字串:
from itertools import combinations
s = 'hi|guys|whats|app'
splits = 2
indexes = [i for i, c in enumerate(s) if c == '|']
for I in combinations(indexes, splits):
print([s[i 1:j] for i, j in zip([-1, *I], [*I, None])])
輸出:
['hi', 'guys', 'whats|app']
['hi', 'guys|whats', 'app']
['hi|guys', 'whats', 'app']
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/317707.html
