我有一个IEnumerable,其中SaleReport的模型如下:
public int ID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal Amount { get; set; }
public SalesReportProduct Product { get; set; }
public int ItemID { get; set; }
public int LanguageID { get; set; }
public int ProductID { get; set; }
我使用基于dateTime值的db条目填充此IEnumerable:
salesReports = _salesReport.GetAll(fromDate, toDate);
然后我有一个int列表,它们都是可用的ItemID:
var ItemIDList = new List<int>();
我的问题是我必须插入所有不在IEnumerable中的ItemID的SalesReport,因此对于ItemIDList的每个值,我检查IEnumerable中是否至少有一个相应的ItemID,如果不是,我有附加具有该ItemID的新SalesReport。
我怎样才能轻松完成这项工作?
答案 0 :(得分:1)
您可以使用Range
&amp; Except
可以执行此操作。
var unusedIds = Enumerable.Range(1, _salesReport.select(sr => sr.ItemID).Max())
.Except(_salesReport.select(sr => sr.ItemID));
ItemIDList.AddRange(unusedIds);
我不知道Except
函数有多贵,猜测它会为Find
中的_salesReport
范围内的每个项目执行Except
。我会查一查并回复你。
。 。 。当然我错了Jon Skeets Eudlinq Max()
的实现只消耗每个序列一次,ILSpy向我展示了.Net源代码中的类似优化。
NB :调用_salesReport
以获取整数范围 - 当然 - 会迭代_salesReport
一次,所以总共迭代{{1}两次。
如果这太贵了,您可以从_salesReport
var usedIds = _salesReport.select(sr => sr.ItemID).ToList();
var unusedIds = Enumerable.Range(1, usedIds.Max()).Except(usedIds);
ItemIDList.AddRange(unusedIds);
。 。 。实际上,你可以节省一个号码。 我们检查列表中是否有Max(),但当然我们知道Max在列表中,因为我们从列表中得到它,因此我们不需要在范围内包含Max我们要检查的数字。
var usedIds = _salesReport.select(sr => sr.ItemID).ToList();
var unusedIds = Enumerable.Range(1, usedIds.Max() - 1).Except(usedIds);
ItemIDList.AddRange(unusedIds);
答案 1 :(得分:0)
作为练习,我试图以最有效的方式解决这个问题:
var reports = _salesReports.OrderBy(x=>x.ItemId).Select(x=>x.ItemId);
var requiredReports = ItemIdList.OrderBy(x=>x);
int reportsCount = reports.Count();
int requiredCount = requiredReports.Count();
List<int> missingReports = new List<int>();
int reportIndex = 0;
int requiredIndex = 0;
while (reportIndex < reportsCount && requiredIndex < requiredCount)
{
if (reports[reportIndex] == requiredReports[requiredIndex])
{
reportIndex++;
requiredIndex++;
continue;
}
if (reports[reportIndex] < requiredReports[requiredIndex])
{
reportIndex++;
continue;
}
if (reports[reportIndex] > requiredReports[requiredIndex])
{
missingReports.Add(requiredReports[requiredIndex]);
requiredIndex++;
continue;
}
}
for (var i = requiredIndex; i < requiredCount; i++ )
{
missingReports.Add(requiredReports[i]);
}
显然,为了清晰的代码,你应该使用Linq。这是为了避免多次迭代列表,但这样做的成本对于清楚理解代码的能力是值得的。