Как построить все возможные пары из строковых символов

#python #split #combinations

Вопрос:

Я хочу из строки построить пары, содержащие все возможные комбинации символов строки.

 # Exemple :
s = "ABCD"

# Desired result :
["A", "BCD"]
["B", "ACD"]
["C", "ABD"]
...
["AB", "CD"]
...
["BC", "AD"]
...
["ABC", "D"]
["ABD", "C"]
["ACD", "B"]
["BCD", "A"]
 

Ответ №1:

Один из способов состоит в том, чтобы создавать комбинации индексов, а не самих элементов с увеличением r : 1, 2,.., длина — 1. Затем мы находим оставшиеся индексы после выбора комбинации. itemgetter можно получить значения, заданные индексами, и мы можем собрать их в список в виде строк:

 from itertools import combinations
from operator import itemgetter

# given string and range till its length
s = "ABCD"
rng = range(len(s))

result = []
# for each combination possibility r...
for r in range(1, len(s)):
    # get the indices from `rng`
    for inds in combinations(rng, r):
        # find `others` that are not `inds` in `rng`
        others = [ind for ind in rng if ind not in inds]

        # now index into the string with these indices to find pairs
        first = itemgetter(*inds)(s)
        second = itemgetter(*others)(s)

        # store the stringifed pair
        result.append(["".join(first), "".join(second)])
 

что дает

 >>> result

[["A", "BCD"],
 ["B", "ACD"],
 ["C", "ABD"],
 ["D", "ABC"],
 ["AB", "CD"],
 ["AC", "BD"],
 ["AD", "BC"],
 ["BC", "AD"],
 ["BD", "AC"],
 ["CD", "AB"],
 ["ABC", "D"],
 ["ABD", "C"],
 ["ACD", "B"],
 ["BCD", "A"]]
 

Ответ №2:

Вы можете использовать двоичное представление числа с n двоичными цифрами: Ноль означает, что соответствующий символ должен идти влево, а единица-что он должен идти вправо:

 def pairs(s):
    for mask in range(1, 2**len(s) - 1):
        pair = ["", ""]
        for i, ch in enumerate(s):
            pair[(mask >> i) amp; 1]  = ch
        yield pair
 

Пример использования:

 print(list(pairs("ABCD"))
 

Ответ №3:

Не уверен, что это соответствует вашим потребностям, но more_ittools.set_partitions может быть решением.

 from more_itertools import set_partitions

iterable = 'abcd'

for part in set_partitions(iterable, k=2):
    print([''.join(p) for p in part])
 

С принтами:

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

Ответ №4:

Вы можете использовать рекурсивную функцию генератора:

 def pairs(d, c = []):
  if not d and len(c) == 2:
     yield c
  elif d:
     for i, a in enumerate(d):
       if not c or len(c) == 1:
          yield from pairs(d[:i] d[i 1:], c [a])
       if c:
          yield from pairs(d[:i] d[i 1:], c[:-1] [c[-1] a])

print(list(pairs('ABCD')))
 

Выход:

 [['A', 'BCD'], ['A', 'BDC'], ['AB', 'CD'], ['ABC', 'D'], ['AB', 'DC'], ['ABD', 'C'], ['A', 'CBD'], ['A', 'CDB'], ['AC', 'BD'], ['ACB', 'D'], ['AC', 'DB'], ['ACD', 'B'], ['A', 'DBC'], ['A', 'DCB'], ['AD', 'BC'], ['ADB', 'C'], ['AD', 'CB'], ['ADC', 'B'], ['B', 'ACD'], ['B', 'ADC'], ['BA', 'CD'], ['BAC', 'D'], ['BA', 'DC'], ['BAD', 'C'], ['B', 'CAD'], ['B', 'CDA'], ['BC', 'AD'], ['BCA', 'D'], ['BC', 'DA'], ['BCD', 'A'], ['B', 'DAC'], ['B', 'DCA'], ['BD', 'AC'], ['BDA', 'C'], ['BD', 'CA'], ['BDC', 'A'], ['C', 'ABD'], ['C', 'ADB'], ['CA', 'BD'], ['CAB', 'D'], ['CA', 'DB'], ['CAD', 'B'], ['C', 'BAD'], ['C', 'BDA'], ['CB', 'AD'], ['CBA', 'D'], ['CB', 'DA'], ['CBD', 'A'], ['C', 'DAB'], ['C', 'DBA'], ['CD', 'AB'], ['CDA', 'B'], ['CD', 'BA'], ['CDB', 'A'], ['D', 'ABC'], ['D', 'ACB'], ['DA', 'BC'], ['DAB', 'C'], ['DA', 'CB'], ['DAC', 'B'], ['D', 'BAC'], ['D', 'BCA'], ['DB', 'AC'], ['DBA', 'C'], ['DB', 'CA'], ['DBC', 'A'], ['D', 'CAB'], ['D', 'CBA'], ['DC', 'AB'], ['DCA', 'B'], ['DC', 'BA'], ['DCB', 'A']]