2013-05-10 4 views
6

Wie generiere ich alle möglichen Kombinationen einer Zeichenfolge mit Leerzeichen zwischen den Zeichen?Wie erzeuge ich alle möglichen Kombinationen einer Zeichenfolge mit Leerzeichen zwischen den Zeichen? Python

[in]: "foobar" 

[out]: 
['foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar', 
'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar', 
'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r', 
'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r', 
'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r', 
'f o o b a r', 'foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 
'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 
'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 
'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 
'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 
'f oo b a r', 'fo o b a r', 'f o o b a r'] 
+0

Hinweis: Sie könnte prüfen, an jeder Position eine Zeichenfolge aufzuteilen, und dann tun rekursiv das gleiche für jede Teilzeichen –

+2

Wie kommen Sie Ihre Ausgabe so sehr verändert? – jamylak

Antwort

3
import itertools as it 

def func(s): 
    if not s: 
     return [s] 
    binary = it.product(['',' '], repeat=len(s)-1) 
    zipped = (it.izip_longest(s , comb, fillvalue='') for comb in binary) 
    return [''.join(it.chain.from_iterable(x)) for x in zipped] 

func('foobar') 

output:

['foobar', 
'fooba r', 
'foob ar', 
'foob a r', 
'foo bar', 
'foo ba r', 
'foo b ar', 
'foo b a r', 
'fo obar', 
'fo oba r', 
'fo ob ar', 
'fo ob a r', 
'fo o bar', 
'fo o ba r', 
'fo o b ar', 
'fo o b a r', 
'f oobar', 
'f ooba r', 
'f oob ar', 
'f oob a r', 
'f oo bar', 
'f oo ba r', 
'f oo b ar', 
'f oo b a r', 
'f o obar', 
'f o oba r', 
'f o ob ar', 
'f o ob a r', 
'f o o bar', 
'f o o ba r', 
'f o o b ar', 
'f o o b a r'] 
+0

dies erzeugt den falschen Ausgang – jamylak

+0

@jamylak - nein, tut es nicht. – root

+0

haben Sie 32 Kombinationen im Gegensatz zu OPs 64. Auch Ihre Combos sind rückwärts. Etwas wie 'für x im Produkt (('', ''), repeat = len (Text)):' 'L.append (''. Join (chain.from_iterable (izip (Text, umgekehrt (x)))) .rstrip()) 'sollte es beheben – jamylak

1

Dies ist wahrscheinlich nicht der effizienteste Weg, aber ich würde zwei Listen machen. Einer hat einen Buchstaben als jedes Element, und der andere hat jeden Buchstaben gefolgt von einem Leerzeichen. (Überspringe den letzten Buchstaben jedes Mal, da er immer keinen Platz hat.) Ein möglicher Abstand wird erzeugt, indem zwischen den beiden Listen für jeden Buchstaben gewählt wird (der als binäre Zahl modelliert werden kann, wobei 0 = kein Leerzeichen und 1 = Leerzeichen)

def spacify(word): 
    no_space = list(word[:-1]) 
    spaced = [lt + ' ' for lt in no_space] 
    for i in range(2 ** (len(word) - 1)): 
     spaced_word = "" 
     for j in range(len(word) - 1): 
      if i % 2 == 0: 
       spaced_word += no_space[j] 
      else: 
       spaced_word += spaced[j] 
      i = i // 2 # Or use bit shifting to be fancy 
    print spaced_word + word[-1] 
+0

Keine generische Lösung. Weder ein effizienter noch. –

+0

eigentlich müssen Sie nur bis zu 2 ** 4 (16 Kombinationen) gehen, weil Sie den ersten und letzten Buchstaben des Wortes strippen müssen. – lucasg

+1

Die Lösung ist nicht ganz korrekt, da nach dem letzten Buchstaben kein Platz sein sollte. Dies verringert auch die Anzahl der Möglichkeiten. Jetzt reparieren. – Titandrake

1
from itertools import combinations 

def gen_spaces(data): 
    return_value = [] 
    size = len(data)-1 
    for num_spaces in range(size): 
     for comb in combinations(range(size), num_spaces+1): 
      data_as_list = list(data) 
      for i in comb: 
       data_as_list[i] +=' ' 
      return_value.append(''.join(data_as_list)) 
    return return_value 

from pprint import pprint 

pprint(gen_spaces("foobar")) 

Ausgang:

['f oobar', 
'fo obar', 
'foo bar', 
'foob ar', 
'fooba r', 
'f o obar', 
'f oo bar', 
'f oob ar', 
'f ooba r', 
'fo o bar', 
'fo ob ar', 
'fo oba r', 
'foo b ar', 
'foo ba r', 
'foob a r', 
'f o o bar', 
'f o ob ar', 
'f o oba r', 
'f oo b ar', 
'f oo ba r', 
'f oob a r', 
'fo o b ar', 
'fo o ba r', 
'fo ob a r', 
'foo b a r', 
'f o o b ar', 
'f o o ba r', 
'f o ob a r', 
'f oo b a r', 
'fo o b a r', 
'f o o b a r'] 

Update:

Sie haben erwähnt, Sie brauchen „alle po ssible Kombinationen einer Zeichenfolge mit Leerzeichen zwischen den Zeichen ", aber zur gleichen Zeit das Beispiel, das Sie in [Out] angegeben haben, spiegelt das nicht wider (d. h. Sie haben zweimal "f o o bar", "f ooba r" fehlen, etc.)

In dieser Antwort, die ich nehme an, Sie „alle möglichen Kombinationen von einer Zeichenkette mit Leerzeichen zwischen den Zeichen“ wollen

0

Mit itertools Bibliothek wirklich (aber es ist so ziemlich das gleiche wie Titandrake):

import itertools 

foobar = "foobar" 
foobar_r = range(len(foobar)) 


for integer in range(2**5): 
    binary_mask = [ bit for bit in itertools.ifilter(lambda x: (integer >>x)&0x01, foobar_r) ] 
    spaces_mask = [ " " if i in binary_mask else "" for i in foobar_r ] 

    # Zip-it Crash-it Melt-it Upgrade-it 
    print integer, "".join([ "".join([str(char) for char in zip_char ]) for zip_char in itertools.izip(foobar,spaces_mask)]) 
1

Hier eine Implementierung meiner rekursive Idee ist oben:

def string_spaces(s): 
    ret = set([s]) # use a set rather than a list to prevent duplicates 
    for i in range(1, len(s)): 
     for fst in string_spaces(s[:i]): 
      for snd in string_spaces(s[i:]): 
       ret.add(fst + ' ' + snd) 
    return ret 

Beispiel:

In [11]: string_spaces('foo') 
Out[11]: set(['foo', 'f o o', 'f oo', 'fo o']) 

NB: Python eine Rekursion Grenze von 1000 Stack-Frames hat, so dass dies für sehr lange Strings (länger als 1.000 Zeichen) zum Absturz bringen.

2
from itertools import product 

text = "foobar" 
L = [''.join(reversed(x)).rstrip() 
    for x in product(*[(c, c+' ') for c in reversed(text)])] 
print L 

['foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r', 'f o o b a r', 'foobar', 'f oobar', 'fo obar', 'f o obar', 'foo bar', 'f oo bar', 'fo o bar', 'f o o bar', 'foob ar', 'f oob ar', 'fo ob ar', 'f o ob ar', 'foo b ar', 'f oo b ar', 'fo o b ar', 'f o o b ar', 'fooba r', 'f ooba r', 'fo oba r', 'f o oba r', 'foo ba r', 'f oo ba r', 'fo o ba r', 'f o o ba r', 'foob a r', 'f oob a r', 'fo ob a r', 'f o ob a r', 'foo b a r', 'f oo b a r', 'fo o b a r', 'f o o b a r'] 
+0

sehr elegant. Ich habe nie gedacht, 'Produkt' mit' umgekehrt' zu verwenden =) – alvas

1

Recursive Lösung. (Kann die Verwendung von sys.setrecursionlimit() für längere Strings benötigen):

def gen_perm(my_str): 
    if len(my_str) <= 1 : 
     return [my_str] 
    rest_perms = gen_perm(my_str[1:]) 
    all_perms = [my_str[0] + perm for perm in rest_perms ] + [my_str[0] + ' ' + perm for perm in rest_perms] 
    return all_perms 

print(gen_perm("foobar")) 
Verwandte Themen