2013-08-01 67 views
0

我有兩個列表通過LINQ返回。我的目標是將'默認'列表中的所有項目減去'notDefaults'列表中的內容。排除使用linq的項目

我目前正在通過兩個嵌套for循環並使用'RemoveAt'來做到這一點。這隻能用一個LINQ語句來完成嗎?基本上,除非項目存在於表「AssetPayrollMarkupOverrides」中,否則我需要'默認'列表中的所有內容。

自從it appears to be slow以來我擔心使用'RemoveAt'。

var defaults = (from a in dbcontext.Assets 
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID 
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID 
    join d in dbcontext.StateLookups on c.StateID equals d.StateID 
    where d.ShortName == state 
    select new AssetMarkup() 
    { 
     AssetId = a.AssetID, 
     AssetName = a.AssetName, 
     Seg1_Code = a.Seg1_Code, 
    }).ToList(); 


var notDefaults = (from a in dbcontext.Assets 
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID 
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID 
    join d in dbcontext.StateLookups on c.StateID equals d.StateID 
    join e in dbcontext.AssetPayrollMarkupOverrides on a.AssetID equals e.AssetID 
    where d.ShortName == state 
    select new AssetMarkup() 
    { 
     AssetId = a.AssetID, 
     AssetName = a.AssetName, 
     Seg1_Code = a.Seg1_Code, 
     ShortName = d.ShortName, 
     OfficePercentage = e.OfficePercentage, 
     MaintenancePercentage = e.MaintenancePercentage, 
     Note = e.Note 
    }).ToList(); 

我本來就這樣,以確保這兩個列表匹配:

var defaults = (from a in dbcontext.Assets 
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID 
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID 
    join d in dbcontext.StateLookups on c.StateID equals d.StateID 
    where d.ShortName == state 
    select new AssetMarkup() 
    { 
     AssetId = a.AssetID, 
     AssetName = a.AssetName, 
     Seg1_Code = a.Seg1_Code, 
     ShortName = d.ShortName, 
     OfficePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.OfficePercentage).FirstOrDefault(), 
     MaintenancePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.MaintenancePercentage).FirstOrDefault(), 
     Note = dbcontext.AssetPayrollMarkupOverrides.Where(x => x.AssetID == a.AssetID).Select(x => x.Note).FirstOrDefault() 
    }).ToList(); 

var notDefaults = (from a in dbcontext.Assets 
    join b in dbcontext.AssetAddresses on a.AssetID equals b.AssetID 
    join c in dbcontext.Addresses on b.AddressID equals c.AddressID 
    join d in dbcontext.StateLookups on c.StateID equals d.StateID 
    join e in dbcontext.AssetPayrollMarkupOverrides on a.AssetID equals e.AssetID 
    where d.ShortName == state 
    select new AssetMarkup() 
    { 
     AssetId = a.AssetID, 
     AssetName = a.AssetName, 
     Seg1_Code = a.Seg1_Code, 
     ShortName = d.ShortName, 
     OfficePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.OfficePercentage).FirstOrDefault(), 
     MaintenancePercentage = dbcontext.PayrollMarkups.Where(x => x.StateID == c.StateID).Select(x => x.MaintenancePercentage).FirstOrDefault(), 
     Note = dbcontext.AssetPayrollMarkupOverrides.Where(x => x.AssetID == a.AssetID).Select(x => x.Note).FirstOrDefault() 
    }).ToList(); 

return Json(defaults.Except(notDefaults).OrderBy(x => x.AssetName).ToDataSourceResult(request)); 

回答

0
var notDefaultIds = notDefaults.Select(nd => nd.AssetID); 
var result = defaults.Where(def => !notDefaultIds.Any(id => id == def.AssetID); 

看到,如果你想降低分貝往返,從notDefaults移動ToList()defaultsresult;

4

您可以使用Except

var remaining = defaults.Except(notDefaults); 

您可能需要確保AssetMarkup是你的相等比較設置爲以非基於參考的方式比較對象。

這裏 http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

+0

我很抱歉沒有在我原來的文章中說明這一點,但我確實試圖使用'除外',但它似乎沒有工作。我還在每個linq聲明中添加了相同的OfficePercentage,MaintenancePercentage和Notes,以確保它們完全匹配,並且「Except」仍然不起作用。 return Json(defaults.Except(notDefaults).OrderBy(x => x.AssetName).ToDataSourceResult(request)); – Mithrilhall

+0

您需要確保您有Equals重載,才能正確比較AssetMarkup對象。 –

1

您要找的是兩套中的complement。 LINQ的Except()方法是專門做這個(你可以使用,其採用的IEqualityComparer過載):

public class AssetMarkupComparer : IEqualityComparer<AssetMarkup> 
{ 
    public bool Equals(AssetMarkup am1, AssetMarkup am2) 
    { 
     return am1.AssetId == am2.AssetId; 
    } 

    public int GetHashCode(AssetMarkup obj) 
    { 
     return obj.AssetId.GetHashCode(); 
    } 
} 

var complement = defaults.Except(notDefaults, new AssetMarkupComparer()); 

你需要考慮在比較器方法零點但這只是一個骨架的例子。