为具有值的动态属性列表生成所有可能的组合

时间:2015-02-23 12:12:05

标签: c# algorithm

我很难为属性列表生成所有可能的组合及其可能的值。我想要实现的是这样的方法:

public List<Variant> generateAllPossibleVariants(List<Attribute> attributes)

属性类如下所示:

public class Attribute {
    public String Name { get; set; }
    public ICollection<String> PossibleValues { get; protected set; }
}

因此,假设您有一个2个属性的列表(虽然计数是动态的)及其可能的值:

attributeColor with possible Values of ( "red", "blue" )
attributeSize with possible values of ("XL", "L" )

现在我的方法应该返回一个Variant List,而Variant Class看起来如下:

public class Variant
{
    public IDictionary<Attribute, string> AttributeValues { get; private set; }
}

现在我的方法应该返回所有组合的List,如下所示:

List<Variant> :
    Variant.AttributeValues { attributeColor => "red", attributeSize => "XL" }
    Variant.AttributeValues { attributeColor => "red", attributeSize => "L" }
    Variant.AttributeValues { attributeColor => "blue", attributeSize => "XL" }
    Variant.AttributeValues { attributeColor => "blue", attributeSize => "L" }

2 个答案:

答案 0 :(得分:0)

您正在寻找cartesian product(动态维度)。

实现它的一种简单方法是在维度上使用递归,并且每次在递归结果和其中一个维度上调用笛卡尔积。

伪代码:

genAllPossibilities(list attributes) //each element in attributes is a list
   if length(attributes) == 1:
        return attributes[0] //the only element, which is a list of one attribute
   else:
        curr = head(attributes) // first element in the list
        reminder = tails(attributes) // a list of all elements except the first
        return cartesianProduct(genAllPossibilities(reminder), curr)

cartesianProduct(list1, list2):
     l = new list
     for each x1 in list1:
         for each x2 in list2:
                l.append(new MyObject(x1,x2))
      return l

答案 1 :(得分:0)

这不是优化的代码,但您可以自己理解并清理它:

public void Main()
{
    var attr1 = new MyAttribute  { Name = "Colors", PossibleValues = new List<string> { "red", "blue" } };
    var attr2 = new MyAttribute  { Name = "Sizes", PossibleValues = new List<string> { "XL", "L" } };   
    var attr3 = new MyAttribute  { Name = "Shapes", PossibleValues = new List<string> { "qube", "circle" } };   
    var attrList = new List<MyAttribute> { attr1, attr2, attr3 };

    var result = attrList.Skip(1).Aggregate<MyAttribute, List<Variant>>(
        new List<Variant>(attrList[0].PossibleValues.Select(s => new Variant { AttributeValues = new Dictionary<MyAttribute, string> { {attrList[0], s} } })),
        (acc, atr) =>
        {
            var aggregateResult = new List<Variant>();

            foreach (var createdVariant in acc)
            {
                foreach (var possibleValue in atr.PossibleValues)
                {
                    var newVariant = new Variant { AttributeValues = new Dictionary<MyAttribute, string>(createdVariant.AttributeValues) };
                    newVariant.AttributeValues[atr] = possibleValue;
                    aggregateResult.Add(newVariant);
                }
            }

            return aggregateResult;
        });
}

public class MyAttribute
{
    public string Name { get; set; }
    public ICollection<string> PossibleValues { get; set; }
}

public class Variant
{
    public IDictionary<MyAttribute, string> AttributeValues { get; set; }
}