public class ScenarioResults
{
public string ProductSubType { get; set; }
public string SubBook { get; set; }
public decimal? ScenarioValue { get; set; }
}
我有两个" ScenarioResults"对象。 我需要获得一个新列表,其中的值与两个列表中的scenariovalue不同。
减法标准:
StartResults和EndResults是我拥有的两个列表。我将结果添加到结果列表中 我写了下面的代码,它可以工作:
var results = new List<ScenarioResults>();
foreach (var endResult in resultsEnd)
{
var result = ScenarioResults.Clone(endResult);
var startResult = resultsStart.FirstOrDefault(x.SubBook == result.SubBook && x.ProductSubType == result.ProductSubType);
if (startResult == null)
{
result.ScenarioValue = endResult.ScenarioValue;
results.Add(result);
}
else
{
result.ScenarioValue = endResult.ScenarioValue - startResult.ScenarioValue;
results.Add(result);
}
}
foreach (var startResult in resultsStart)
{
var result = ScenarioResults.Clone(startResult);
var endResult = resultsEnd.Any(x.SubBook == result.SubBook && x.ProductSubType == result.ProductSubType);
if (!endResult)
{
result.ScenarioValue = -startResult.ScenarioValue;
results.Add(result);
}
}
有没有更好的方法来解决这个问题? 如何提高这个性能?
答案 0 :(得分:1)
如果您使用在搜索中使用的组合键对两个集合进行分组,即{SubBook, ProductSubType}
var startDict = resultsStart
.GroupBy(r => new {r.SubBook, r.ProductSubType})
.ToDictionary(g => g.Key, g => g.First());
var endDict = resultsEnd
.GroupBy(r => new {r.SubBook, r.ProductSubType})
.ToDictionary(g => g.Key, g => g.First());
foreach (var key in startDict.Keys.Union(endDict.Keys)) {
var hasStart = startDict.TryGetValue(key, out var start);
var hasEnd = endDict.TryGetValue(key, out var end);
if (hasStart && hasEnd) {
... // Construct the difference with subtraction
} else if (hasStart) {
... // Construct the difference where only the start is present
} else if (hasEnd) {
... // Construct the difference where only the end is present
}
}
由于哈希查找,此解决方案为O(S + E),而由于嵌套线性搜索,原始解决方案为O(S * E)。
答案 1 :(得分:1)
用纯LINQ :)。这只是一个展示可能必须稍微调整但仍然可以做到这一点。只是为了表明一个想法。
List<ScenarioResults> a = new List<ScenarioResults> { new ScenarioResults { ProductSubType = "1", SubBook = "1", ScenarioValue = 10}, new ScenarioResults { ProductSubType = "2", SubBook = "2", ScenarioValue = 10 } };
List<ScenarioResults> b = new List<ScenarioResults> { new ScenarioResults { ProductSubType = "2", SubBook = "2", ScenarioValue = 10 }, new ScenarioResults { ProductSubType = "3", SubBook = "3", ScenarioValue = 10 } };
List<ScenarioResults> result = a.Concat(b.Select(_ => new ScenarioResults { ProductSubType = _.ProductSubType, SubBook = _.SubBook, ScenarioValue = -_.ScenarioValue ?? 0}))
.GroupBy(x => new {x.ProductSubType, x.SubBook})
.SelectMany(g => g.Select(_ => new ScenarioResults { ProductSubType = _.ProductSubType, SubBook = _.SubBook, ScenarioValue = (g.First().ScenarioValue ?? 0) + g.Skip(1).Sum(v => v.ScenarioValue)}))
.Distinct(new EqualityComparer())
.ToList();
其中EqualityComparer
是这样的:
public class EqualityComparer : IEqualityComparer<ScenarioResults>
{
public bool Equals(ScenarioResults x, ScenarioResults y)
{
return x.ProductSubType == y.ProductSubType && x.SubBook == y.SubBook;
}
public int GetHashCode(ScenarioResults obj)
{
return obj.ProductSubType.GetHashCode() ^ obj.SubBook.GetHashCode();
}
}