Home > database >  Create multiple for i in X depending on a given number
Create multiple for i in X depending on a given number

Time:11-29

I want to create a class in python that contains variables and a domain for each variable to generate a list of dictionary containing all the possible solutions for variables assignments

for exemple:
x='x'
y='y'
domainx=[1,2]
domainy=[3,4]

def solutions(elt,elt2,domainx,domainy):

   for i in domainx:
       for j in domainy:
               liste.append({elt:i,elt2:j})
   return liste

liste now is equal to [{'x':1,'y'=3},{'x':1,'y'=4},{'x':2,'y':3} etc..]

but this function it's not flexible and reutilizable because i must declare the variable one by one. what i want is generate solutions from a liste like : liste=[(x,[1,2]),(y,[3,4])or liste=[(x,[324,3433]),(y,[43,34354,45]),(z,[5445,653,3,34,4,5])]

then i pass the liste to a function that will generate the solutions,i don't know how to do it especially that i should do as many as the length of liste is.

My purpose for this question is to create this class,

class CST:

    def __init__(self):
        self.variables=[]
        self.contraintes=[]
        self.VarWithdomaines=[]

  
    def addVarDom(self,variable,domain):
        self.VarWithdomaines.append((variable,domain))
    
    # def generate(self): it's not the correct way
        # liste=[]
        # for repitition in range(len(self.domaines)):
        
        #     solution={}
        #     for noeud in self.domaines:
        #             var=noeud[0]
        #             for x in noeud[1]:
        #                 solution[var]=x
                        
        #     liste.append(solution)
        # return liste
    
    

    
    
Game=CST()


domain = [int(i) for i in range(2)]
domain2 = [int(i) for i in range(3)]
domain3 = [int(i) for i in range(21)]
# domain4 = [int(i) for i in range()]
Game.addVarDom("E1",domain)
Game.addVarDom("E2",domain2)
Game.addVarDom("C20",domain3)



listofsolutions=Game.generate())
#list should be for exemple list=[{E1:1,E2:0,C20:20},{E1:0,E2:2,C20:12}...]
 

CodePudding user response:

Try using itertools!

Essentially, itertools.product does what you want. As explained in the docs, this function takes the Cartesian product of input iterables. So, list(itertools.product([0, 1], [2, 3])) produces [(0, 2), (0, 3), (1, 2), (1, 3)], which is basically all you want.

All that's left is converting that output to the format you're looking for:

import itertools

def assignments(names, values):
    combinations = itertools.product(*values)
    return [
        {
            name: value
            for name, value in zip(names, combination)
        }
        for combination in combinations
    ]

assignments(['x', 'y', 'z'], [[1, 2], [3, 4], [5, 6]])

This would produce the array

[
    {'x': 1, 'y': 3, 'z': 5},
    {'x': 1, 'y': 3, 'z': 6},
    {'x': 1, 'y': 4, 'z': 5},
    {'x': 1, 'y': 4, 'z': 6},
    {'x': 2, 'y': 3, 'z': 5},
    {'x': 2, 'y': 3, 'z': 6},
    {'x': 2, 'y': 4, 'z': 5},
    {'x': 2, 'y': 4, 'z': 6},
]

CodePudding user response:

Thanks to @BrownieInMotion I have modified the methods in the class and it's worked, modified methods:

def addVarDom(self,variable,domain):
        self.variables.append(variable)
        self.domaines.append(domain)
    
    def generate(self):#names, values):
        combinations = itertools.product(*self.domaines)
        return [
            {
                name: value
                for name, value in zip(self.variables, combination)
            }
            for combination in combinations
        ]
  • Related