-1

I have multiple strings on different lines where I want to get all of the possible permutations without changing the order:

for example:

er r er
er er r

which would give me:

er r er
er er r
er r r
er er er

Is there a way to do this is python? If this is a duplicate please advise but I was not able to find one.

This is different from questions like Finding all possible permutations of a given string in python where only one string is used

Update [Still does not work]

import itertools

with open(in_file) as f:
    lis = list(f) 

print (lis)
print([' '.join(x) for x in itertools.product(*map(set, zip(*map(str.split, lis))))])

[Error]

[['er', 'r', 'er'], ['er', 'er', 'r']]
Traceback (most recent call last):
File "test.py", line 37, in <module>
print([' '.join(x) for x in itertools.product(*map(set, zip(*map(str.split, S))))])
TypeError: descriptor 'split' requires a 'str' object but received a 'list'
badner
  • 768
  • 2
  • 10
  • 31
  • 3
    Possible duplicate of [Finding all possible permutations of a given string in python](https://stackoverflow.com/questions/8306654/finding-all-possible-permutations-of-a-given-string-in-python) – Kallz Aug 01 '17 at 04:13
  • @Kallz but this one only has one string, this I can do... the problem is getting combinations between multiple strings. – badner Aug 01 '17 at 04:18
  • Can you show the data in `in_file`? Note: You are `split()`ing twice, `lis = list(f)` would be sufficient. You could of course just put `f` into the `map()` directly (and move the `print` into the `with` clause). Or you can get rid of the `map()` and just `zip(*lis)` – AChampion Aug 01 '17 at 05:54
  • @AChampion the in_file is exactly the same as my example – badner Aug 01 '17 at 05:55
  • Then why are you splitting twice? – AChampion Aug 01 '17 at 05:56
  • @AChamion I can fix that – badner Aug 01 '17 at 05:58
  • @AChampion the output is still the same even without the extra split – badner Aug 01 '17 at 06:02
  • Your error must be incorrect `lis` should be `['er r er', 'er er r']` not the split version you are showing. – AChampion Aug 01 '17 at 06:11

1 Answers1

2

You can zip the splits of these strings and take the cartesion product, e.g.:

>>> import itertools as it
>>> s1, s2 = 'er r er', 'er er r'
>>> {' '.join(x) for x in it.product(*zip(s1.split(), s2.split()))}
{'er er er', 'er er r', 'er r er', 'er r r'}

You can get duplicates so, constructed as a set comprehension.

Updated for an arbitrary number of strings:

>>> import itertools as it
>>> ss = ['er r er', 'er er r', 'ar er r']
>>> {' '.join(x) for x in it.product(*zip(*map(str.split, ss)))}
{'ar er er', 'ar er r', 'ar r er', 'ar r r', 'er er er', 'er er r', 'er r er', 'er r r'}

Note: You could also apply the set to the arguments to product to remove duplicates and it might be quicker depending on the overlaps of the strings, e.g.:

>>> [' '.join(x) for x in it.product(*map(set, zip(*map(str.split, ss))))]
['er r r', 'er r er', 'er er r', 'er er er', 'ar r r', 'ar r er', 'ar er r', 'ar er er']

To read from a file type object:

>>> with open(in_file) as f:
...     lis = list(f)
>>> print([' '.join(x) for x in it.product(*map(set, zip(*map(str.split, lis))))])
['er r r', 'er r er', 'er er r', 'er er er']

Or more compactly:

>>> with open(in_file) as f:
...     print([' '.join(x) for x in it.product(*map(set, zip(*map(str.split, f))))])
['er r r', 'er r er', 'er er r', 'er er er']
AChampion
  • 29,683
  • 4
  • 59
  • 75
  • I would like an example that isn't fixed for two strings as I could have more. I will update my question. – badner Aug 01 '17 at 04:38
  • 1
    Please do, as it would require an extraordinary feat of inference to work that out from your question. Note: This is quite easy to update for an arbitrary number of strings. – AChampion Aug 01 '17 at 04:42
  • I am getting at , zip is a tuple right? – badner Aug 01 '17 at 04:50
  • `zip()` is a builtin function that takes multiple lists and returns an `iterator` (or `list` py2) of `tuple`s of all the first elements, all the second elements, etc. – AChampion Aug 01 '17 at 04:53
  • I was thinking something like this: print (' '.join(x for x, _ in itertools.product(S))) I appended my strings to a list hoping that wold help – badner Aug 01 '17 at 04:59
  • and with print({' '.join(x) for x in itertools.product(*zip(*map(str.split, S)))}) I got set(['r', 'er']) – badner Aug 01 '17 at 05:03
  • I would update your question with what you have tried. Showing how `S` is defined, and describe your expected results. – AChampion Aug 01 '17 at 05:33
  • ok I have put the code and current error up, I got rid of the extra things I was doing. – badner Aug 01 '17 at 05:37
  • See my comment, not sure why you are `split()`ing twice. – AChampion Aug 01 '17 at 05:54
  • yes, I was trying to make it more obvious but it was unnecessary and I agree with that and produces the same result. Your updated solution is perfect. I would also like to than k you for your patience and help on this. The magic in this solution is the change in format from several strings separated by '\n' to a list of strings (not what I imagined but a working solution) and the use of product from itertools. Thanks again! – badner Aug 01 '17 at 11:39