迭代IEnumerable <ienumerable <object>&gt;时避免'System.OutOfMemoryException'

时间:2017-09-04 13:53:58

标签: c#

我有以下代码来获取满足requiredNumbers标准的最便宜对象列表。此对象列表的长度可以从1到 maxLength ,即可以允许重复的对象的1到 maxLength 的组合。现在,这将遍历整个组合列表(IEnumerable of IEnumerable of OBJECT)罚款直到maxLength = 9并在之后用“System.OutOfMemoryException”打破

 t1.Concat(new OBJECT[] { t2 }

我尝试了另一种解决方法(在代码注释中提到),但这似乎有自己的恶魔。我现在理解的是,我必须以某种方式知道最低价格的对象组合,而不是迭代整个组合列表,我似乎无法找到它。

有人可以建议任何让 maxLength 更高(理想情况下更高)的更改,而不会影响性能。任何帮助深表感谢。如果我不清楚,请告诉我。

    private static int leastPrice = int.MaxValue;

    private IEnumerable<IEnumerable<OBJECT>> CombinationOfObjects(IEnumerable<OBJECT> objects, int length)
    {
        if (length == 1)
            return objects.Select(t => new OBJECT[] { t });

        return CombinationOfObjects(objects, length - 1).SelectMany(t => objects, (t1, t2) => t1.Concat(new OBJECT[] { t2 }));
    }

    //Gets the least priced Valid combination out of all possible
    public IEnumerable<OBJECT> GetValidCombination(IEnumerable<OBJECT> list, int maxLength, int[] matArray)
    {
        IEnumerable<IEnumerable<OBJECT>> tempList = null;

        List<IEnumerable<OBJECT>> validList = new List<IEnumerable<OBJECT>>();

        for (int i = 1; i <= maxLength; i++)
        {
            tempList = CombinationOfObjects(list, i);

            tempList = from alist in tempList
                       orderby alist.Sum(x => x.Price)
                       select alist;

            foreach (var lst in tempList)
            {
                //This check will not be required if the least priced value is returned as soon as found
                int price = lst.Sum(c => c.Price);
                if (price < leastPrice)
                {
                    if (CheckMaterialSum(lst, matArray))
                    {
                        validList.Add(lst);
                        leastPrice = price;
                        break;
                        //return lst;
                        //returning lst as soon as valid combo is found is fastest
                        //Con being it also returns the least priced least item containing combo
                        //i.e. even if a 4 item combo is cheaper than the 2 item combo satisfying the need,
                        //it'll never even check for the 4 item combo

                    }
                }
            }
        }

        //This whole thing would go too if lst was returned earlier
        foreach (IEnumerable<OBJECT> combination in validList)
        {
            int priceTotal = combination.Sum(combo => combo.Price);
            if (priceTotal == leastPrice)
            {
                return combination;
            }
        }

        return new List<OBJECT>();
    }

     //Checks if the given combination satisfies the requirement 
    private bool CheckMaterialSum(IEnumerable<OBJECT> combination, int[] matArray)
    {
        int[] sumMatProp = new int[matArray.Count()];

        for (int i = 0; i < matArray.Count(); i++)
        {
            sumMatProp[i] = combination.Sum(combo => combo.Numbers[i]);
        }

        bool isCombinationValid = matArray.Zip(sumMatProp, (requirement, c) => c >= requirement).All(comboValid => comboValid);

        return isCombinationValid;
    }

    static void Main(string[] args)
    {
        List<OBJECT> testList = new List<OBJECT>();

        OBJECT object1 = new OBJECT();
        object1.Name = "object1";
        object1.Price = 2000;
        object1.Numbers = new int[] { 2, 3, 4 };
        testList.Add(object1);

        OBJECT object2 = new OBJECT();
        object2.Name = "object2";
        object2.Price = 1900;
        object2.Numbers = new int[] { 3, 2, 4 };
        testList.Add(object1);

        OBJECT object3 = new OBJECT();
        object3.Name = "object3";
        object3.Price = 1600;
        object3.Numbers = new int[] { 4, 3, 2 };
        testList.Add(object1);

        int requiredNumbers = new int[]{10,10,10};
        int maxLength = 9;//This is the max length possible, OutOf Mememory exception after this
        IEnumerable<OBJECT> resultCombination = GetValidCombination(testList, maxLength, requiredNumbers);

    }

修改

要求:

我有许多具有多个属性的对象,即 Price Name Materials 。现在,我需要找到这些对象的组合,即组合中所有材料的总和满足用户输入的材料数量。此外,组合需要尽可能低的价格。 存在 maxLength 的约束,它设置了组合中可以包含的最大对象总数,即对于 maxLength = 8,组合可以包含1中的任意值到8个物体。

尝试了方法:

1

  

- 我找到了所有对象组合(有效+无效)

     

- 对它们进行迭代以找到价格最低的组合。迭代时这会耗尽内存。

    2。
      

    - 我找到所有可能的组合(有效+无效)

         

    - 应用有效性检查(即,如果它满足用户要求)

         

    - 仅在列表列表中添加有效组合

         

    - 对这个有效的列表列表进行迭代,找到最便宜的列表并返回。也是内存不足

    3

      

    - 我按照对象的递增顺序找到组合(即首先是所有具有1个对象的组合,然后是2然后等等......)

         

    - 根据价格排序组合

         

    - 应用有效性检查并返回第一个有效组合

         

    - 这样做效果很好,但并不总是返回最便宜的组合。

    如果我能以某种方式获得最佳解决方案而不迭代整个列表,那将解决它。但是,我尝试的所有事情要么必须迭代所有组合,要么根本不会产生最佳解决方案。

    对于我似乎无法想到的其他一些方法的任何帮助都是最受欢迎的。

0 个答案:

没有答案