Ile można uzyskać z ciągu znaków, takiego jak , np. abcd
?Podłoża ciągu znaków przy użyciu języka Python
Jak mogę uzyskać wszystkie jego podciągi:
['a', 'b', 'c', 'd', 'ab', 'bc', 'cd', 'abc', 'bcd', 'abcd']
Ile można uzyskać z ciągu znaków, takiego jak , np. abcd
?Podłoża ciągu znaków przy użyciu języka Python
Jak mogę uzyskać wszystkie jego podciągi:
['a', 'b', 'c', 'd', 'ab', 'bc', 'cd', 'abc', 'bcd', 'abcd']
Spróbuj tego:
def consecutive_groups(iterable):
s = tuple(iterable)
for size in range(1, len(s)+1):
for index in range(len(s)+1-size):
yield iterable[index:index+size]
>>> print list(consecutive_groups('abcd'))
['a', 'b', 'c', 'd', 'ab', 'bc', 'cd', 'abc', 'bcd', 'abcd']
A liczba kombinacji jest po prostu równa sumie od 1 do długości łańcucha, co jest równoważne z n * (n + 1)/2
.
Przy okazji, jeśli chcesz uniknąć duplikatów, można po prostu użyć lokalnie zdefiniowane ustawienia w funkcji generatora, tak:
def consecutive_groups(iterable):
s = tuple(iterable)
seen = set()
for size in range(1, len(s)+1):
for index in range(len(s)+1-size):
slc = iterable[index:index+size]
if slc not in seen:
seen.add(slc)
yield slc
Ten kod jest trochę bardziej nieporęczny i prawdopodobnie mógłby być zoptymalizowany pod kątem wcięcia, ale zrobi to za dowód koncepcji.
To jest to, co chcesz:
In [260]: S = 'abcd'
In [261]: list(itertools.chain.from_iterable([list(itertools.combinations(S,i)) for i in range(1,len(S))]))
Out[261]:
[('a',),
('b',),
('c',),
('d',),
('a', 'b'),
('a', 'c'),
('a', 'd'),
('b', 'c'),
('b', 'd'),
('c', 'd'),
('a', 'b', 'c'),
('a', 'b', 'd'),
('a', 'c', 'd'),
('b', 'c', 'd')]
A jeśli naprawdę chcesz je wszystkie jako ciągi znaków, można zrobić:
In [262]: combos = list(itertools.chain.from_iterable([list(itertools.combinations(S,i)) for i in range(1,len(S))]))
In [263]: [''.join(c) for c in combos]
Out[263]:
['a',
'b',
'c',
'd',
'ab',
'ac',
'ad',
'bc',
'bd',
'cd',
'abc',
'abd',
'acd',
'bcd']
EDIT, aby tylko dostać podciągi z S
:
In [270]: list(itertools.chain.from_iterable([[S[i:i+k] for i in range(len(S)-k)] for k in range(1,len(S)+1)])) + [S]
Out[270]: ['a', 'b', 'c', 'ab', 'bc', 'abc', 'abcd']
Myślę, że chcesz 'itertools.combinations (S, i + 1)', aby uzyskać niezmieniony ciąg też. Również 'lista' i nawiasy kwadratowe wokół twojego wewnętrznego generatora są niepotrzebne. 'chain.from_iterable' jest całkowicie szczęśliwy biorąc generatory z generatora. – Blckknght
jest pustą częścią ciągu rozwiązania? Jeśli tak, to też go brakuje. Myślę, że 'ac' również nie jest poprawnym rozwiązaniem, ponieważ pomiędzy tymi słowami brakuje' b'. – hochl
dla drugiej (EDYCJA Aby uzyskać tylko podłańcuchy S :) jak znaleźć tylko podciągi o długości x? – Mathime
Istnieją dwa pytania .
Pierwszy How many substrings can you make out of a string like “abcd”?
jest to kombinacje tak:
import itertools
s='abcd'
com=[list(itertools.combinations(s,x)) for x in range(1,len(s)+1)]
print [''.join(e) for e in sum(com,[])]
drukuje:
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'bc', 'bd', 'cd', 'abc', 'abd', 'acd', 'bcd', 'abcd']
Drugie pytanie brzmi, jak powtórzyć swój przykład (który nie jest 'Połączenie'). Można zrobić z tym kodem:
>>> [s[i:i+j] for j in range(1,len(s)+1) for i in range(len(s)-j+1)]
['a', 'b', 'c', 'd', 'ab', 'bc', 'cd', 'abc', 'bcd', 'abcd']
Dlaczego downstream? –
Nie spadłem, ale najprawdopodobniej dlatego, że 'ac' nie jest częścią rozwiązania. – hochl
@hochl: Dodałem kod do replikowania przykładu OP –
myślę, że to działa też i jednocześnie nie jest najbardziej wydajny, ma atrakcyjny korzystania z mniej skomplikowanych funkcji.
S = "abcd"
substrings = [S[i:j] for i in range(len(S)) for j in range(i+1,len(S)+1)]
substrings.sort(key=len)
Należy jednak zauważyć, że to podejście nie usuwa identycznych podciągów, które mogą się pojawić. Na przykład, jeśli oryginalny podciąg był "abcdab"
, pojawiłby się dwa razy.
Aby nie uwzględniać duplikatów podciągów, zmień zrozumienie listy "[...]" na zrozumienie ustawione "{...}". – mbomb007
Czy to wystarczy?
import itertools
def substrings(x):
for i, j in itertools.combinations(xrange(len(x)+1), 2):
yield x[i:j]
lub wyrażenia generatora:
(x[i:j] for i, j in itertools.combinations(xrange(len(x)+1), 2))
Rozwinięta wynik na swoim przykładzie wygląda następująco:
['a', 'ab', 'abc', 'abcd', 'b', 'bc', 'bcd', 'c', 'cd', 'd']
Aby zamówić według długości, użyj sort key=len
.
Zadajesz dwa różne pytania: "Ile kombinacji możesz zrobić ...?" i "Jak mogę to uzyskać jak ...". Odpowiedzi na te dwa pytania są bardzo różne. –
@MarceloCantos Nie rozumiem, jak to prawda. Jedna jest tylko długością drugiej. Możesz utworzyć 'sum (1 ... n)', tzn. 'N * n (-1)/2' [substrings] (https://en.wikipedia.org/wiki/Substring) ciągu o długości' n'. –