2012-10-17 40 views
10

Có bao nhiêu substrings bạn có thể tạo ra một chuỗi như abcd không?Đường con của chuỗi bằng cách sử dụng Python

Làm thế nào tôi có thể nhận được tất cả các chuỗi con của nó:

['a', 'b', 'c', 'd', 'ab', 'bc', 'cd', 'abc', 'bcd', 'abcd'] 
+2

Bạn đang đặt hai câu hỏi khác nhau: "Bạn có thể tạo bao nhiêu kết hợp ...?" và, "Làm thế nào tôi có thể làm cho nó trông giống như ...". Câu trả lời cho hai câu hỏi này rất khác nhau. –

+0

@MarceloCantos Tôi không thấy nó đúng như thế nào. Một là chiều dài của cái kia. Bạn có thể tạo 'sum (1 ... n)', tức là 'n * n (-1)/2' [substrings] (https://en.wikipedia.org/wiki/Substring) của một chuỗi chiều dài' n'. –

Trả lời

10

Hãy thử điều này:

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'] 

Và số kết hợp chỉ đơn giản là bằng tổng từ 1 tới độ dài của chuỗi, tương đương với n * (n + 1)/2.

Bằng cách này, nếu bạn muốn tránh trùng lặp, bạn chỉ có thể sử dụng một địa phương xác định thiết lập trong chức năng máy phát điện, như vậy:

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 

đang Đó là một chút khó sử dụng hơn và có lẽ có thể là được tối ưu hóa cho thụt đầu dòng, nhưng nó sẽ làm cho một bằng chứng về khái niệm.

+0

Tôi không phải là downvoter của bạn, nhưng nó không hoàn toàn đúng. Hãy thử 'map (partial (reduce, operator.add), powerset ('abcd'))'. – wberry

+0

Đã chỉnh sửa, vui lòng kiểm tra lại. –

+0

máy phát điện làm cho hulk hạnh phúc! +1 O.o – hochl

2

Đây là những gì bạn muốn:

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')] 

Hoặc nếu bạn thực sự muốn tất cả chúng như dây đàn, bạn có thể làm:

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 Để có được chỉ chuỗi con của 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'] 
+0

Tôi nghĩ rằng bạn muốn 'itertools.combinations (S, i + 1)', để có được chuỗi không thay đổi quá. Ngoài ra, 'danh sách' và dấu ngoặc vuông xung quanh trình tạo bên trong của bạn là không cần thiết. 'chain.from_iterable' là hoàn toàn hạnh phúc lấy máy phát điện từ một máy phát điện. – Blckknght

+0

là phần chuỗi rỗng của một giải pháp? Nếu có, bạn cũng bỏ lỡ nó. Tôi nghĩ 'ac' không phải là giải pháp hợp lệ vì' b' bị thiếu ở giữa. – hochl

+0

cho cái thứ hai (CHỈNH SỬA Để chỉ lấy các phần của S :) thì làm cách nào tôi chỉ tìm được các chuỗi có chiều dài x? – Mathime

1

Có hai câu hỏi ở đó .

Đầu tiên, How many substrings can you make out of a string like “abcd”? là một sự kết hợp như thế này:

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,[])] 

in:

['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'bc', 'bd', 'cd', 'abc', 'abd', 'acd', 'bcd', 'abcd'] 

Câu hỏi thứ hai là làm thế nào để tái tạo ví dụ của bạn (mà không phải là một 'kết hợp'). Bạn có thể làm điều đó với mã này:

>>> [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'] 
+0

Tại sao downvote? –

+2

Tôi không downvote nhưng hầu hết có lẽ vì 'ac' không phải là một phần của giải pháp. – hochl

+0

@hochl: Tôi đã thêm mã để sao chép ví dụ OP của –

1

Tôi nghĩ việc này quá và trong khi không phải là hiệu quả nhất, nó có hấp dẫn của việc sử dụng các tính năng ít phức tạp.

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) 

Lưu ý rằng cách tiếp cận này không loại bỏ các chất nền giống hệt nhau có thể xuất hiện. Ví dụ: nếu chuỗi con ban đầu là "abcdab", a, bab sẽ xuất hiện hai lần.

+0

Để không bao gồm các bản sao trùng lặp, hãy thay đổi danh sách hiểu '[...]' thành một tập đọc '{...}'. – mbomb007

7

Điều này có làm được không?

import itertools 
def substrings(x): 
    for i, j in itertools.combinations(xrange(len(x)+1), 2): 
     yield x[i:j] 

hoặc là biểu hiện phát:

(x[i:j] for i, j in itertools.combinations(xrange(len(x)+1), 2)) 

Kết quả mở rộng ví dụ của bạn trông như thế này:

['a', 'ab', 'abc', 'abcd', 'b', 'bc', 'bcd', 'c', 'cd', 'd'] 

Để đặt theo chiều dài, sử dụng loại key=len.

Các vấn đề liên quan