使用Linq检查孙子列表时删除子列表项

时间:2015-04-30 04:57:33

标签: c# linq

以下代码显示了我如何将数据分配到IEnumerable<UnCompletedJobDetailsBO>

有一个列表(IEnumerable<UnCompletedJobDetailsBO>)有另一个列表(List<JobDetailsBO>),其子列表(List<JobDetailsBO>)上面有一个列表。但AllocationDetailList只有一个列表项。

public IEnumerable<UnCompletedJobDetailsBO> GetControlDetails(DateTime startDate)
{
    var controlDetails =
       (from booking in db.BookingDetail
        where booking.BookingDateTime >= startDate
        orderby booking.DocketNo
        select new UnCompletedJobDetailsBO()
        {
            CustomerName = booking.Customer.Name,
            CompanyName = booking.CompanyDetail.Name,
            JobList =
               (from job in db.BookingJob.Where(x => x.BookingID == booking.BookingID) //get job list
                select new JobDetailsBO()
                {
                    JobID = job.JobID,
                    JobType = job.JobType,
                    ItemName = job.ItemName,
                    AllocationDetailList =
                       (from jobAllocationDetail in db.JobAllocation
                        join returnUnCollected in db.JobReturnUnCollected
                            on jobAllocationDetail.JobAllocationDetailID
                            equals returnUnCollected.JobAllocationDetailID
                            into returnJob

                        from returnUnCollected in returnJob.DefaultIfEmpty()
                        where (jobAllocationDetail.Booking.BookingID == booking.BookingID)
                        select new AllocationBO()
                        {
                            JobUnCollectedID = returnJob.JobUnCollectedID,
                            JobType = jobAllocationDetail.JobType,
                            CurrentStatus = jobAllocationDetail.CurrentStatus,
                        }).DefaultIfEmpty().ToList(),
                }).DefaultIfEmpty().ToList(),
        }).ToList();

    return controlDetails;
}

如果内部列表(JobList)项满足以下条件,我想删除AllocationDetailList项。有时AllocationDetailList可能为空,所以我也检查了。但是当我写下面的查询时,它不会删除满足条件的特定JobList项。提前谢谢。

public List<UnCompletedJobDetailsBO> RemovePODFromSelectedList(
    List<UnCompletedJobDetailsBO> unCompletedJobDetailsBO)
{
    unCompletedJobDetailsBO
        .SelectMany(y => y.JobList)
        .ToList()
        .RemoveAll(x => ((x.AllocationDetailList[0] != null) ?
            x.AllocationDetailList[0].JobType == "D" &&
                x.AllocationDetailList[0].JobUnCollectedID == null &&
                x.AllocationDetailList[0].CurrentStatus == 5 :
            x.AllocationDetailList.Count > 1));

    return unCompletedJobDetailsBO;
}

2 个答案:

答案 0 :(得分:2)

如果没有a good, minimal, complete code example,我不确定是否可以解决任何性能问题。很难完全理解这个问题,但是如果不能真正测试代码,重现和观察特定的性能问题,很难确定你的问题具体在哪里。 ,不管怎么解决它。

也就是说,根据您发布的代码, 清除了为什么不从列表中删除项目。基本问题是虽然SelectMany()方法确实具有允许您将所有不同JobList对象中的所有元素枚举为单个枚举的效果,但这些元素被枚举为枚举。

当你致电ToList()时,你正在从新的枚举中创建一个全新的列表,当你调用RemoveAll()时,你只是从新列表中删除元素,而不是从中删除它们的列表最初来了。

你说你可以使用for循环。我猜你的意思是这样的:

public List<UnCompletedJobDetailsBO> RemovePODFromSelectedList(
    List<UnCompletedJobDetailsBO> unCompletedJobDetailsBO)
{
    foreach (var item in unCompletedJobDetailsBO)
    {
        item.JobList.RemoveAll(x => ((x.AllocationDetailList[0] != null) ?
            x.AllocationDetailList[0].JobType == "D" &&
                x.AllocationDetailList[0].JobUnCollectedID == null &&
                x.AllocationDetailList[0].CurrentStatus == 5 :
            x.AllocationDetailList.Count > 1));
    }

    return unCompletedJobDetailsBO;
}

注意:无需返回unCompletedJobDetailsBO。整个对象没有变化,更不用说变量了。代码修改的唯一内容是传入对象的成员中的每个单独的JobList对象。即上述方法的实际返回类型可能为voidreturn语句可以完全删除。

可能您可以通过以不同方式删除元素来加快代码速度。 List<T>.RemoveAll()方法实际上是合理有效的,O(n)成本。但它仍然涉及在删除第一个元素之后复制列表中的所有数据(以便所有元素在列表中向下移动)。如果您必须订购列表,这可能与您可以做的一样好,但如果没有,您可以采用不同的方式处理删除,或者完全使用不同的数据结构,在一个或多个元素的删除成本较低的情况下无序。

但是,再一次,没有更多的细节,没有一个好的例子来解决这个特定的问题在这里似乎并不实用。

答案 1 :(得分:0)

条件

x.AllocationDetailList[0] != null 
如果AllocationDetailList中没有项目,

将抛出异常。相反,你需要检查

x.AllocationDetailList!=null && x.AllocationDetailList.Count>0.

在代码中的SelectMany之后的.ToList()将创建一个新列表,并且将从该新列表中删除项目而不是unCompletedJobDetailsBO。您需要修改删除功能,如下所示

   unCompletedJobDetailsBO.ForEach(y => y.JobList.RemoveAll(x => ((x.AllocationDetailList != null && x.AllocationDetailList.Count>0) 
                                                                         ?
                                                                         x.AllocationDetailList[0].JobType == "D"
                                                                           && x.AllocationDetailList[0].JobUnCollectedID == null
                                                                           && x.AllocationDetailList[0].CurrentStatus == "5" 
                                                                         :
                                                                        x.AllocationDetailList.Count > 1
                                                                         )
                                                                   ));