python - performance generating combinations of objects with combinations of attr -
i looking advice on how can better approach couple of functions.
i have set of 5 objects 6 attributes on each, number of objects can change amount of attributes.
i need iterate on each possible combination of attribute, on each possible combination of object. no object in set can feature same value within set. , each objects attributes there n possible values ( n set size ). values applicable attributes cannot applicable attribute. ie. attributea's value, never value attributeb.
at moment have objects represented list of lists. eg. [[obj1attr_a, obj1attrb], [obj2attr_a, obj2attr_b]] etc
the problem itertools.combinations returns many redundent combinations not valid ( ie. values appear more once ). if use generator return valid combinations slow never yields correct combination. there way filter results in itertools.combinations efficiently?
#keywords list of possible values each attribute solver.get_unique_combinations( itertools.combinations(itertools.product(*keywords), 5)) def get_unique_combinations(combinations): combination in combinations: flat = [item sublist in combination item in sublist] if len(set(flat)) < len(flat): continue yield combination
ive tried using ifilter same problem (below), way can see going able use other itertools.combinations return sets of objects unique values in each , somehow skip need filter altogether.
return itertools.ifilter(lambda x: solver.get_unique_combinations(x), itertools.combinations(itertools.product(*keywords), 5)) @staticmethod def get_unique_combinations(x): if len( set(str(x).replace('[', '') .replace('[', '') .replace(',', '') .replace('(', '') .replace(')', '') .split())) == len(x) * len(x[0]): return true return false
**edit: requested - short compilable version:
import itertools def has_unique_values(iterable, attr_count): seen = set() seen_add = seen.add counter = 0 element in itertools.ifilterfalse(seen.__contains__, itertools.chain(iterable)): seen_add(element) counter += 1 return counter == attr_count keywords = [ ["australia", "sweden", "germany", "france", "italy"], ["lion", "tiger", "otter", "bird", "fish"], ["table", "chair", "cloth", "couch", "tv"], ["apple", "orange", "pear", "grape", "tomato"], ["onion", "carrot", "mushroom", "kale", "spinach"]] keyword_combinations = itertools.product(*keywords) population = len(keywords[0]) attr_count = len(keywords) unique_count = population * attr_count c in itertools.ifilter(lambda x: has_unique_values(x, unique_count), itertools.combinations(keyword_combinations, population)): print c #doesnt here
Comments
Post a Comment