增强以下组合算法的性能

时间:2017-08-28 07:20:52

标签: c# performance combinatorics

我使用以下代码来获取对象输入列表的所有组合,同时限制组合的大小(maxComboCount)。代码虽然做了什么问题,但是很慢。有人可以看看并建议任何有助于提高表现的变化。

  

E.g。   输入:

List<int> input = new List<int>() {obj1, obj2, obj3};
int maxComboCount = 2;
  

输出:

     

[obj1],[obj2],[obj3],

     

[obj1,obj1],[obj1,obj2],[obj1,obj3],

     

[obj2,obj1],[obj2,obj2],[obj2,obj3],

     

[obj3,obj1],[obj3,obj2],[obj3,obj3]

public static IEnumerable<List<T>> GetCombo<T>(List<T> listObject, int maxComboCount)
{
     var resultList = new List<List<T>>();
     var distinctObjects = listObject.Distinct().ToList();

     for (int j = 0; j < distinctObjects.Count(); j++)
     {
         var objPosition = distinctObjects[j];

         var newList = new List<T>();
         newList.Add(objPosition);

         if (newList.Count() <= maxComboCount)
         {
             resultList.Add(newList);
         }

         var listMinusOneObject = listObject.Select(x => x).ToList();
         listMinusOneObject.Remove(listMinusOneObject.Where(x => Compare(x, objPosition)).First());
            //Compare method returns true if the objects are equal

         if (listMinusOneObject.Any())
         {
             GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref resultList, maxComboCount);
         }
        }
        return resultList;
}

public static void GetAllCombinationsOfAllSizes<T>(List<T> listObject, List<T> growingList, ref List<List<T>> returnResult, int maxComboCount)
{
    var distinctObjects = listObject.Distinct().ToList();

    for (int j = 0; j < distinctObjects.Count(); j++)
    {
        var objPosition = distinctObjects[j];
        var newList = growingList.ToList();
        newList.Add(objPosition);

        if (newList.Count() <= maxComboCount)
        {
            returnResult.Add(newList);
        }

        var listMinusOneObject = listObject.Select(x => x).ToList();
        listMinusOneObject.Remove(listMinusOneObject.Where(x => Compare(x, objPosition)).First());

        if (listMinusOneObject.Any())
        {
            GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref returnResult, maxComboCount);
        }
    }
}

修改

这是我的类,包含了被重写的Equals和GetHashCode

public class Material
{
    public int Price { get; set; }
    public string Name { get; set; }
    public int Num1 { get; set; }
    public int Num2 { get; set; }
    public int Num3 { get; set; }
    public bool isInStock { get; set; }

    public override bool Equals(object obj)
    {
        Material material = obj as Material;
        return material != null &&
            material.Price == this.Price &&
            material.Name == this.Name &&
            material.Num1 == this.Num1 &&
            material.Num2 == this.Num2 &&
            material.Num3 == this.Num3 &&

    }

    public override int GetHashCode()
    {
        return this.Price.GetHashCode() ^
            this.Name.GetHashCode() ^
            this.Num1.GetHashCode() ^
            this.Num2.GetHashCode() ^
            this.Num3.GetHashCode() ^

    }
}

1 个答案:

答案 0 :(得分:1)

所以基本上你在寻找排列。其中很多都可以简化。要删除重复项,您可以将HashSet传递给它而不是List。这将消除比较对象的需要,这将加速该过程。

以下是我前一段时间使用的以下函数,用于获取指定HashSet的{​​{1}}内所有对象的排列:

length

您可以将以下函数组合使用,以便在指定static IEnumerable<IEnumerable<T>> PermutationOfObjects<T>(IEnumerable<T> objects, int length) { if (length == 1) return objects.Select(t => new T[] { t }); return PermutationOfObjects(objects, length - 1).SelectMany(t => objects, (t1, t2) => t1.Concat(new T[] { t2 })); } 的{​​{1}}内获得所有排列:

HashSet

致电:

maxLength

回归:

  

[obj1],[obj2],[obj3]
  [obj1,obj1],[obj1,obj2],[obj1,obj3]
  [obj2,obj1],[obj2,obj2],[obj2,obj3]
  [obj3,obj1],[obj3,obj2],[obj3,obj3]

几个例子:

enter image description here enter image description here

修改

当使用类static IEnumerable<IEnumerable<T>> AllPermutations<T>(IEnumerable<T>list, int maxLength) { IEnumerable<IEnumerable<T>> newList = null; for (int i = 1; i <= maxLength; i++) { if (newList == null) { newList = PermutationOfObjects(list, i); } else newList = newList.Union(PermutationOfObjects(list, i)); } return newList; } 以使HashSet使用HashSet<OBJECT> input = new HashSet<OBJECT>() { obj1, obj2, obj3}; int maxComboCount = 2; IEnumerable<IEnumerable<OBJECT>> perms = AllPermutations(input, maxComboCount); OBJECT作为基于值的相等性检查而不是基于引用的相等性检查时,您需要声明您的类:

注意:注意方法包括类的两个变量,如果只需要根据特定变量将对象视为相等,则只需要包含定义“唯一性”的变量。 / p>

Equals

之后,您的输出不应该有重复项。