ramobal
ramobal

Reputation: 261

how to get all possible combinations of strings/words with each word multiple times

I'm trying to create all possible stochiometries of chemical compounds, which essentially is combining strings/words: Let's say I have a list of elements:

els=['Ba','Ti','O']

and I say the number of each element can be maximally 3 and I want all possible combinations,with always each element at least once. The desired output would be: ['BaTiO','BaTiO2','BaTiO3','BaTi2O','BaTi2O2','BaTi2O3'.....]

AND the input list should be of arbitrary length, e.g. if it is els=['Ba','Sr','Ti','O'] i want as a result: ['BaSrTiO','BaSrTiO2'....] (the output could also be of the form [BaTiO,BaTiOO,BaTiOOO…] instead of the numbers) I tried to come up with something using itertools, but I can't find a way how to do it.

Any suggestions?

Upvotes: 0

Views: 131

Answers (2)

Jan Joswig
Jan Joswig

Reputation: 733

You could use itertools.permutations for a shorter and maybe a bit more readable solution:

from itertools import permutations

elements = {"Ba", "Ti", "O"}  # Set of elements
maxi = 3                      # Maximum occurrence

raw_output = permutations(range(1, maxi + 1), len(elements))
for i in raw_output:
    str_output = " ".join([f"{e}{v}" for e, v in zip(elements, i)])
    print(str_output)

>>> O1 Ba2 Ti3
    O1 Ba3 Ti2
    O2 Ba1 Ti3
    O2 Ba3 Ti1
    O3 Ba1 Ti2
    O3 Ba2 Ti1

Upvotes: 1

ramobal
ramobal

Reputation: 261

The solution was actually pretty easy in the end, just using "product" from itertools and the "pymatgen" library.

phase_space=['Ba','Ti','O']
maxi=5

list1=[]

for ii in range(len(phase_space)):
    list1.append(list(range(1,1+maxi)))

new_list=list(product(*list1))

formulas=dict()
formula_list=[]
for ii in range(len(phase_space)):
    formulas[phase_space[ii]]=1
for ii in range(len(new_list)):
    for jj in range(len(phase_space)):
        formulas[phase_space[jj]]=new_list[ii][jj]
    comp = mg.Composition.from_dict(formulas)
    if len(list(comp.as_dict().values()))>=2:
        formula_list.append(comp.alphabetical_formula)


print(formula_list)  

The output then is as desired:

['Ba1 O1 Ti1', 'Ba1 O2 Ti1', 'Ba1 O3 Ti1', 'Ba1 O4 Ti1', 'Ba1 O5 Ti1', 'Ba1 O1 Ti2', 'Ba1 O2 Ti2', 'Ba1 O3 Ti2', 'Ba1 O4 Ti2', 'Ba1 O5 Ti2', 'Ba1 O1 Ti3', 'Ba1 O2 Ti3', 'Ba1 O3 Ti3', 'Ba1 O4 Ti3', 'Ba1 O5 Ti3', 'Ba1 O1 Ti4', 'Ba1 O2 Ti4', 'Ba1 O3 Ti4', 'Ba1 O4 Ti4', 'Ba1 O5 Ti4', 'Ba1 O1 Ti5', 'Ba1 O2 Ti5', 'Ba1 O3 Ti5', 'Ba1 O4 Ti5', 'Ba1 O5 Ti5', 'Ba2 O1 Ti1', 'Ba2 O2 Ti1', 'Ba2 O3 Ti1', 'Ba2 O4 Ti1', 'Ba2 O5 Ti1', 'Ba2 O1 Ti2', 'Ba2 O2 Ti2', 'Ba2 O3 Ti2', 'Ba2 O4 Ti2', 'Ba2 O5 Ti2', 'Ba2 O1 Ti3', 'Ba2 O2 Ti3', 'Ba2 O3 Ti3', 'Ba2 O4 Ti3', 'Ba2 O5 Ti3', 'Ba2 O1 Ti4', 'Ba2 O2 Ti4', 'Ba2 O3 Ti4', 'Ba2 O4 Ti4', 'Ba2 O5 Ti4', 'Ba2 O1 Ti5', 'Ba2 O2 Ti5', 'Ba2 O3 Ti5', 'Ba2 O4 Ti5', 'Ba2 O5 Ti5', 'Ba3 O1 Ti1', 'Ba3 O2 Ti1', 'Ba3 O3 Ti1', 'Ba3 O4 Ti1', 'Ba3 O5 Ti1', 'Ba3 O1 Ti2', 'Ba3 O2 Ti2', 'Ba3 O3 Ti2', 'Ba3 O4 Ti2', 'Ba3 O5 Ti2', 'Ba3 O1 Ti3', 'Ba3 O2 Ti3', 'Ba3 O3 Ti3', 'Ba3 O4 Ti3', 'Ba3 O5 Ti3', 'Ba3 O1 Ti4', 'Ba3 O2 Ti4', 'Ba3 O3 Ti4', 'Ba3 O4 Ti4', 'Ba3 O5 Ti4', 'Ba3 O1 Ti5', 'Ba3 O2 Ti5', 'Ba3 O3 Ti5', 'Ba3 O4 Ti5', 'Ba3 O5 Ti5', 'Ba4 O1 Ti1', 'Ba4 O2 Ti1', 'Ba4 O3 Ti1', 'Ba4 O4 Ti1', 'Ba4 O5 Ti1', 'Ba4 O1 Ti2', 'Ba4 O2 Ti2', 'Ba4 O3 Ti2', 'Ba4 O4 Ti2', 'Ba4 O5 Ti2', 'Ba4 O1 Ti3', 'Ba4 O2 Ti3', 'Ba4 O3 Ti3', 'Ba4 O4 Ti3', 'Ba4 O5 Ti3', 'Ba4 O1 Ti4', 'Ba4 O2 Ti4', 'Ba4 O3 Ti4', 'Ba4 O4 Ti4', 'Ba4 O5 Ti4', 'Ba4 O1 Ti5', 'Ba4 O2 Ti5', 'Ba4 O3 Ti5', 'Ba4 O4 Ti5', 'Ba4 O5 Ti5', 'Ba5 O1 Ti1', 'Ba5 O2 Ti1', 'Ba5 O3 Ti1', 'Ba5 O4 Ti1', 'Ba5 O5 Ti1', 'Ba5 O1 Ti2', 'Ba5 O2 Ti2', 'Ba5 O3 Ti2', 'Ba5 O4 Ti2', 'Ba5 O5 Ti2', 'Ba5 O1 Ti3', 'Ba5 O2 Ti3', 'Ba5 O3 Ti3', 'Ba5 O4 Ti3', 'Ba5 O5 Ti3', 'Ba5 O1 Ti4', 'Ba5 O2 Ti4', 'Ba5 O3 Ti4', 'Ba5 O4 Ti4', 'Ba5 O5 Ti4', 'Ba5 O1 Ti5', 'Ba5 O2 Ti5', 'Ba5 O3 Ti5', 'Ba5 O4 Ti5', 'Ba5 O5 Ti5']

Upvotes: 0

Related Questions