转动前臂链';用于将一个列表中的元素插入linq中的另一个列表
本文关键字:列表 一个 另一个 linq 元素 插入 用于 | 更新日期: 2023-09-27 18:28:51
我已经做了几个小时了,我得到的唯一结论是我需要拿起一本关于Linq的好书。
所以交易是这样的:我有以下类的三个对象列表(从现在起,我将它们称为"父列表":
public class State
{
public int IdState {get; set;}
public string NameState {get; set;}
private IList<City> cityList = new List<City>();
public void AddCity(City city)
{
cityList.Add(city);
}
}
public class City
{
public int IdCity { get; set; }
public string NameCity { get; set; }
public int IdState { get; set; }
private IList<Company> companyList = new List<Company>();
public void AddCompany(Company company)
{
companyList.Add(company);
}
}
public class Company
{
public int IdCompany { get; set; }
public string NameCompany { get; set; }
public int IdCity { get; set; }
}
我认为从这里可以很直接地解释我想要的:一个州的单一列表,其中cityList由该州的适当城市组成,每个公司每个城市的列表由该城市的公司组成。换句话说,一个州的列表,每个州分支到其城市,然后每个城市分支到其中的公司。
所以,我的父母名单是:
private List<State> finalList; //This is the "parent list supreme" which I'll send to the client-side
private List<City> cityList; //Auxiliary
private List<Company> companyList; //Auxiliary; this one does not exist in the actual code but I'm putting it here for simplification purposes
这真的不重要,但多亏了linq的"魔力",我可以用合适的州、城市和公司填写这些列表,然而,我不知道如何通过链接将合适的城市和公司填充到State.cityList和City.companyList中。目前,我使用的是一个非常丑陋的foreach链:
foreach (State state in finalList)
{
foreach (City city in cityList)
{
if (city.IdState == state.IdState)
{
state.AddCity(city);
foreach (Company company in companyList)
{
if (company.idCity == city.IdCity)
city.AddCompany(company);
}
}
}
}
丑,对吧?那么,我该如何用linq实现同样的目标呢?我认为可能还有一个更有效的问题:在这种情况下,是否值得使用linq(它都指向"是",但数字…)?
BTW:这种方式就像我期望的一样
您在这里逻辑上所做的是一个Join操作。您当前的代码实际上是查找所有可能的城市和州对,然后只归档匹配的对。你可以在LINQ中表示这一点,但你不想这样做。有更有效的方法可以执行Join,只生成你需要开始的精确对。LINQ Join
操作符利用了这一点。
您的代码可以归结为两个不同的Join
调用,然后对每个结果进行迭代,根据查询执行对象的突变。
var stateCityPairs = from state in finalList
join city in cityList
on state.IdState equals city.IdState
select new { state, city };
foreach (var pair in stateCityPairs)
pair.state.AddCity(pair.city);
var cityCompanyPairs = from city in cityList
join company in companyList
on city.IdCity equals company.IdCity
select new { city, company };
foreach (var pair in cityCompanyPairs)
pair.city.AddCompany(pair.company);
虽然这实际上是更多的代码,但对于更大的集合来说,这将表现得更好,而且在语义上也代表了代码的意图
我在City和State类中添加了两个方法。不过,如果名单是公开的,那会更容易:
public void AddCities(List<City> cities)
{
cityList.Concat(cities);
}
public void AddCompanies(List<Company> companies)
{
companyList.Concat(companies);
}
你可以使用你想要的聚合器。我通常更喜欢Union,因为它不增加双打,但我想这对你来说并不重要。
她是我在林克的做法:
cityList.ForEach(ci => ci.AddCompanies(companyList.Where(co => co.IdCity == ci.IdCity).ToList()));
finalList.ForEach(s => s.AddCities(cityList.Where(ci => ci.IdState == s.IdState).ToList()));
我先将公司添加到适当的城市,然后将所有城市添加到正确的州。如果您需要更多关于此代码的解释,请随时询问。
使用LINQ,您可能希望将私有IList转换为公共IList(Or List或IEnumerable或IQueryable),以便直接设置它们。
假设finalList已经预先填充了状态:
var finalList=finalList
.Select(fl=>new State
{
fl.IdState,
fl.NameState,
cityList=cityList.Where(cl=>cl.IdState==fl.IdState).Select(cl=>
new City
{
cl.IdCity,
cl.NameCity,
cl.IdState,
companyList=companyList.Where(comp=>
comp.IdState==cl.IdState && comp.IdCity==cl.IdCity)
}
});