首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将列表中的值与另一个列表中的特定和进行比较的最快方法是什么?

将列表中的值与另一个列表中的特定和进行比较的最快方法是什么?
EN

Stack Overflow用户
提问于 2014-03-10 12:23:00
回答 3查看 70关注 0票数 3

我有两个巨大的创建对象列表。一个包含来自不同资源的所有预测的List<Forecast>和一个具有这些资源能力的List<Capacity>

Forecast还包含布尔值,表示该资源是否超过或低于他所有预测的总和。

代码语言:javascript
复制
public class Forecast
{
    public int ResourceId { get; set; }
    public double? ForecastJan { get; set; }
    // and ForecastFeb, ForecastMarch, ForecastApr, ForecastMay, etc.

    public bool IsOverForecastedJan { get; set; }
    // and IsOverForecastedFeb, IsOverForecastedMarch, IsOverForecastedApr, etc.
}

public class Capacity
{
    public int ResourceId { get; set; }
    public double? CapacityJan { get; set; }
    // and CapacityFeb, CapacityMar, CapacityApr, CapacityMay, etc.
}

我必须设置IsOverForecastXXX属性,所以我必须知道每个月对每个资源的预测之和是否高于这个特定资源的容量之和。

这是我的代码:

代码语言:javascript
复制
foreach (Forecast f in forecastList)
{
    if (capacityList.Where(c => c.Id == f.ResourceId)
                    .Select(c => c.CapacityJan)
                    .First()
        < forecastList.Where(x => x.ResourceId == f.ResourceId)
                      .Sum(x => x.ForecastJan)
    )
    {
        f.IsOverForecastedJan = true;
    }

    //Same for each month...
}

我的代码可以工作,但是当列表太大(数千个元素)时,我的性能真的很差。

你能怎样改进这个算法?如何将每种资源的预测和相关容量进行比较?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-10 12:31:37

您可以使用FirstFirstOrdefault获取currect资源的容量,然后比较它们。我会使用类似于ToLookupDictionary来获得所有资源的所有预测。

代码语言:javascript
复制
ILookup<int, Forecast> forecastMonthGroups = forecastList
    .ToLookup(fc => fc.ResourceId);
foreach (Forecast f in forecastList)
{
    double? janSum = forecastMonthGroups[f.ResourceId].Sum(fc => fc.ForecastJan);
    double? febSum = forecastMonthGroups[f.ResourceId].Sum(fc => fc.ForecastFeb);
    var capacities = capacityList.First(c => c.ResourceId == f.ResourceId);
    bool overJan = capacities.CapacityJan < janSum;
    bool overFeb = capacities.CapacityFeb < febSum;
    // ...
    f.IsOverForecastedJan = overJan;
    f.IsOverForecastedFeb = overFeb;
    // ...
}

似乎每个ResourceID只有一个ResourceID,然后我将使用Dictionary存储从ResourceIdCapacity的“方式”,这将进一步提高性能:

代码语言:javascript
复制
ILookup<int, Forecast> forecastMonthGroups = forecastList
    .ToLookup(fc => fc.ResourceId);
Dictionary<int, Capacity> capacityResources = capacityList
    .ToDictionary(c => c.ResourceId);
foreach (Forecast f in forecastList)
{
    double? janSum = forecastMonthGroups[f.ResourceId].Sum(fc => fc.ForecastJan);
    double? febSum = forecastMonthGroups[f.ResourceId].Sum(fc => fc.ForecastFeb);
    bool overJan = capacityResources[f.ResourceId].CapacityJan < janSum;
    bool overFeb = capacityResources[f.ResourceId].CapacityFeb < febSum;
    // ...
    f.IsOverForecastedJan = overJan;
    f.IsOverForecastedFeb = overFeb;
    // ...
}
票数 1
EN

Stack Overflow用户

发布于 2014-03-10 12:39:02

在进入循环之前,我会尝试选择每个月的容量和预测值,这样您就不会每次循环循环时迭代每个列表。

就像这样:

代码语言:javascript
复制
 var capicities = capacityList.GroupBy(c => c.ResourceId).ToDictionary(c=>c.First().ResourceId, c=>c.First().CapacityJan);
 var forecasts = forecastList.GroupBy(x => x.ResourceId).ToDictionary(x => x.First().ResourceId, x => x.Sum(f => f.ForecastJan));
 foreach (Forecast f in forecastList)
 {
     if (capicities[f.ResourceId] < forecasts[f.ResourceId])
     {
         f.IsOverForecastedJan = true;
     }

 }
票数 1
EN

Stack Overflow用户

发布于 2014-03-10 12:45:46

为了加快速度,你可以做很多事情。首先,对forecastList进行一次检查,并对每个月的容量预测进行求和:

代码语言:javascript
复制
var demandForecasts = new Dictionary<int, double?[]>();

foreach (var forecast in forecastList)
{
    var rid = forecast.ResourceId;
    if (!demandForecasts.ContainsKey(rid))
    {
        demandForecasts[rid] = new double?[12];
    }

    var demandForecast = demandForecasts[rid];

    demandForecast[0] += forecast.ForecastJan;
    // etc
    demandForecast[11] += forecast.ForecastDec;
}

对容量进行同样的操作,从而生成一个capacities字典。然后,在forecastList上再循环一次,以设置“over预测性”标志:

代码语言:javascript
复制
foreach (var forecast in forecastList)
{
    var rid = forecast.ResourceId;
    forecast.IsOverForecastedJan = capacities[rid][0] < demandForecast[rid][0];
    // ...
    forecast.IsOverForecastedDec = capacities[rid][11] < demandForecast[rid][11];
}

从这段代码中隐含的12倍代码重复可以明显看出,每个月作为单独属性的建模能力等可能不是最好的方法--使用某种索引集合可以消除重复。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22300015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档