问题描述
我是Linq查询的新手,这个问题遇到了我(在解雇了另一个开发人员之后)。 我正在使用一个货运API,该API为申请中的每个产品/项目返回“ n”个货运价格的列表。响应类为:
=ArrayFormula(
IFNA( // Blank if NA
VLOOKUP(
B2:B,// Unique ID lookup
FILTER( // Gives us the filter conditions on other table
SummaryCitizenship!B2:E,// Key column for VLOOKUP is B
SummaryCitizenship!C2:C=1,SummaryCitizenship!D2:D="Personal Responsibility"
),4,// Index to column 4
0 // Exact match
)
)
)
我有一个针对2个项目的响应模型(但也可以是“ n”个项目),其中一个具有5种货运可能性,没有错误,但是另一个具有两个错误,这意味着一个公司没有该项目的货运服务:
public class FreightSimulation
{
public List<Item> Items { get; set; }
}
public class Item
{
public int Id { get; set; }
public List<ItemFreight> Freights { get; set; }
}
public class ItemFreight
{
public Company Company { get; set; }
public Type Type { get; set; }
public double Price { get; set; }
public int Days { get; set; }
public List<Error> Errors { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Type
{
public int Id { get; set; }
public string Description { get; set; }
}
public class Error
{
public string Message { get; set; }
}
我首先需要一个Linq查询,该查询会带来一个列表,其中子列表在所有项之间是公用的,并且其中没有错误。
在这种情况下,我有类似的东西:
var response = new FreightSimulation
{
Items = new List<Item>
{
new Item
{
Id = 1,Freights = new List<ItemFreight>
{
new ItemFreight
{
Errors = null,Price = 10,Days = 8,Company = new Company
{
Id = 1
},Type = new Type
{
Id = 3
}
},new ItemFreight
{
Errors = null,Price = 20,Days = 3,Company = new Company
{
Id = 1
},Type = new Type
{
Id = 8
}
},Days = 10,Company = new Company
{
Id = 2
},Type = new Type
{
Id = 1
}
},Price = 35,Days = 4,Type = new Type
{
Id = 2
}
},Price = 15,Days = 6,Company = new Company
{
Id = 7468
},Type = new Type
{
Id = 1
}
}
}
},new Item
{
Id = 2,Type = new Type
{
Id = 3
}
},new ItemFreight
{
Errors = new List<Error>
{
new Error
{
Message = "Not found."
}
},Company = new Company
{
Id = 2
},new ItemFreight
{
Errors = new List<Erro>
{
new Error
{
Message = "Not found."
}
},Type = new Type
{
Id = 2
}
},Price = 22,Company = new Company
{
Id = 7468
},Type = new Type
{
Id = 1
}
}
}
}
}
};
因此,在这种情况下,我需要一个列表,其中组合仅是公司1和7468(可以是“ n”个公司)。因此,在第2项中,我对公司2的响应有错误,因此必须消除。结果将是:
Company Id Type Id Error
Item 1 1 3 N
Item 1 1 8 N
Item 1 2 1 N
Item 1 2 2 N
Item 1 7468 1 N
Item 2 1 3 N
Item 2 1 8 N
Item 2 2 1 Y
Item 2 2 2 Y
Item 2 7468 1 N
任何组合公司/类型都可能发生这种情况,因此,如果可能的话,它必须是某种动态查询。
谢谢。
解决方法
您可以获得使任何运费返回错误的公司:
var errorCompanyIds = response.Items
.SelectMany(x => x.Freights)
.Where(y => y.Errors !=null && y.Errors.Any())
.Select(y => y.Company.Id)
.ToList();
然后,您可以创建新列表并过滤该公司的所有货运
var newList = new FreightSimulation
{
Items = response.Items.Select(x => new Item
{
Id = x.Id,Freights = x.Freights.Where(y => !errorCompanyIds.Contains(y.Company.Id)).ToList()
}).ToList()
};
,
这应该有效:
var companyIds = new[] { 1,7468 };
var result = response.Items.SelectMany(i => i.Freights.Select(f => new { itemId = i.Id,Freight = f }))
.Where(i => companyIds.Contains(i.itemId) && (!(i.Freight.Errors?.Any() ?? false)));
您在这里要做的是创建对以保留ID,然后根据所需条件过滤这些对。
或者,您可以先过滤原始货运清单,然后按公司选择:
var companyIds = new[] { 1,7468 };
var result = response.Items.SelectMany(i => i.Freights.Where(f => (!(f.Errors?.Any() ?? false)))
.Select(f => new { itemId = i.Id,Freight = f }))
.Where(i => companyIds.Contains(i.itemId));
以防万一这部分令人困惑:
(!(i.Freight.Errors?.Any() ?? false))
这实际上翻译为:
i.Freight.Errors == null || !i.Freight.Errors.Any()
具有null
错误或没有错误(空收款)的平均运费。