性能生成具有attr

时间:2016-08-08 14:29:46

标签: python python-2.7

我正在寻找一些关于如何更好地处理几个功能的建议。

我有一组5个对象,每个对象有6个属性,对象的数量和属性的数量都可以改变。

我需要在每个可能的对象组合上迭代每个可能的属性组合。集合中的任何对象都不能在集合中具有相同的值。并且对于每个对象属性,有n个可能的值(其中n是设置大小)。适用于属性的值不适用于其他属性。即。 attributeA的值永远不会是attributeB的值。

目前,我将对象表示为列表列表。 例如。 [[obj1attr_A,obj1attrB],[obj2attr_A,obj2attr_B]]等等

问题是itertools.combinations返回了太多无效的redundent组合(即,更经常出现一次的值)。如果我使用生成器只返回有效的组合,那么它很慢,从而无法有效地产生正确的组合。有没有办法有效地过滤itertools.combinations中的结果?

#keywords is a list of possible values for each attribute
Solver.get_unique_combinations(
       itertools.combinations(itertools.product(*keywords), 5))

def get_unique_combinations(combinations):
    for combination in combinations:
        flat = [item for sublist in combination for item in sublist]
        if len(set(flat)) < len(flat):
            continue
        yield combination

我也尝试过使用ifilter同样的问题(下面),实际上我唯一可以看到我能够做到这一点的方法就是使用itertools.combinations以外的东西来返回具有唯一值的对象集在每个,并以某种方式完全跳过了对过滤器的需求。

 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

**编辑:根据要求 - 简短的可编辑版本:

import itertools


def has_unique_values(iterable, attr_count):
    seen = set()
    seen_add = seen.add
    counter = 0
    for 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

for c in itertools.ifilter(lambda x: has_unique_values(x, unique_count), 
         itertools.combinations(keyword_combinations, population)):
    print c #doesnt get to here

0 个答案:

没有答案