c#linq在列表中的子列表上联接
本文关键字:列表 c#linq | 更新日期: 2023-09-27 17:58:06
我有一个列表:var_assets_root
,它有一个子列表:contents
。我可以对根列表进行联接,并通过对var_assets_root
中的索引项进行两次联接,用另外两个列表lst_invtypes_assets
和lst_stations_composite_retribution
中的额外项来扩充它。但我也想对子列表var_assets_root-->contents'b.contents
中的项进行联接,下面的代码到目前为止还没有这样做。观察窗中var_assets_root
的图像>>结构
mysql mysql_object = new mysql();
List<mysql.invtypes_asset> lst_invtypes_assets = mysql_object.dbmysql_invtypes_asset_to_list();
List<mysql.stations_composite_retribution> lst_stations_composite_retribution = mysql_object.dbmysql_select_stastations_composite_retribution_to_list();
var lst_assets_list = new AssetList("134399", "343434SxSFX7qO81LqUCberhS1OQtktMvARFGED0ZRSN5c4XP230SA", "434367527");
lst_assets_list.Query();
var var_assets_root = lst_assets_list.assets.ToList();
var var_assets_root_typeid_station
= from b in var_assets_root
join c in lst_invtypes_assets on b.typeID equals c.typeID
join d in lst_stations_composite_retribution on b.locationID equals d.stationID
select new {b.contents, b.flag, b.itemID, b.locationID, d.solarSystemName, d.security, d.securityClass, d.regionName, b.quantity, b.singleton, b.typeID, c.groupID, c.marketGroupID, c.volume,
c.typeName, c.description};
我已经完成了一个解决方案,对每个内容子列表运行linq查询,并相应地分配值。
private void btn_evenet_Click(object sender, EventArgs e)
{
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
stopwatch1.Start();
mysql mysql_object = new mysql();
List<mysql.invtypes_asset> lst_invtypes_assets = mysql_object.dbmysql_invtypes_asset_to_list();
List<mysql.stations_composite_retribution> lst_stations_composite_retribution = mysql_object.dbmysql_select_stastations_composite_retribution_to_list();
AssetList lst_assets_list = new AssetList("2312099", "J&VNM14RFUkSxSFX7qAAAAAA1OQtktMvYTVZZBhkO23235c4Z&HJKODPQLM", "123231527");
lst_assets_list.Query();
var var_assets_root = lst_assets_list.assets.ToList();
var var_assets_root_typeid_station
= from b in var_assets_root
join c in lst_invtypes_assets on b.typeID equals c.typeID
join d in lst_stations_composite_retribution on b.locationID equals d.stationID
select new { b.contents, b.flag, b.itemID, b.locationID, d.solarSystemName, d.security, d.securityClass, d.regionName, b.quantity, b.singleton, b.typeID, c.groupID, c.marketGroupID, c.volume,
c.typeName, c.description};
var lst_assets_root_typeid_station = var_assets_root_typeid_station.ToList(); // Using .ToArray() is about 200ms faster than .ToList()
stopwatch2.Start();
for (Int32 a = 0; a < lst_assets_root_typeid_station.Count(); a++)
{
if (lst_assets_root_typeid_station[a].contents.Count() >= 0)
{
for (Int32 b = 0; b < lst_assets_root_typeid_station[a].contents.Count(); b++)
{
var var_row_invtypes_assets = lst_invtypes_assets.Where(x => x.typeID == lst_assets_root_typeid_station[a].contents[b].typeID).ToArray();
lst_assets_root_typeid_station[a].contents[b].groupID = var_row_invtypes_assets[0].groupID;
lst_assets_root_typeid_station[a].contents[b].typeName = var_row_invtypes_assets[0].typeName;
lst_assets_root_typeid_station[a].contents[b].description = var_row_invtypes_assets[0].description;
lst_assets_root_typeid_station[a].contents[b].volume = var_row_invtypes_assets[0].volume;
lst_assets_root_typeid_station[a].contents[b].marketGroupID = var_row_invtypes_assets[0].marketGroupID;
if (lst_assets_root_typeid_station[a].contents[b].contents.Count() != 0)
{
for (Int32 c = 0; c < lst_assets_root_typeid_station[a].contents[b].contents.Count(); c++)
{
var_row_invtypes_assets = lst_invtypes_assets.Where(x => x.typeID == lst_assets_root_typeid_station[a].contents[b].contents[c].typeID).ToArray();
lst_assets_root_typeid_station[a].contents[b].contents[c].groupID = var_row_invtypes_assets[0].groupID;
lst_assets_root_typeid_station[a].contents[b].contents[c].typeName = var_row_invtypes_assets[0].typeName;
lst_assets_root_typeid_station[a].contents[b].contents[c].description = var_row_invtypes_assets[0].description;
lst_assets_root_typeid_station[a].contents[b].contents[c].volume = var_row_invtypes_assets[0].volume;
lst_assets_root_typeid_station[a].contents[b].contents[c].marketGroupID = var_row_invtypes_assets[0].marketGroupID;
}
}
}
}
}
stopwatch2.Stop();
stopwatch1.Stop();
lbl_stopwatch1.Text = "Everything: " + stopwatch1.Elapsed.ToString("mm'':ss''.ff"); // 1.53 seconds no debugging
lbl_stopwatch2.Text = "contents sublists: " + stopwatch2.Elapsed.ToString("mm'':ss''.ff"); // contents sublists take 1.03 seconds no debugging
}
}
一旦我知道当调用getAllContents时,"yield"会从一堆内容节点中弹出一个内容节点,我就调整了我的代码和你的函数,这样现在所有内容节点都会递归到linq查询中,并填充它们的空值。此外,在linq创建var_assets_root_typeid_station之后的新代码现在几乎快了一倍。非常感谢。
private void btn_evenet_Click(object sender, EventArgs e)
{
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
stopwatch1.Start();
mysql mysql_object = new mysql();
List<mysql.invtypes_asset> lst_invtypes_assets = mysql_object.dbmysql_invtypes_asset_to_list();
List<mysql.stations_composite_retribution> lst_stations_composite_retribution = mysql_object.dbmysql_select_stastations_composite_retribution_to_list();
AssetList lst_assets_list = new AssetList("12345678", "ABCDEFFGHIKL01235kokJDSD213123", "12345678");
lst_assets_list.Query();
var var_assets_root = lst_assets_list.assets.ToList();
var var_assets_root_typeid_station
= from b in var_assets_root
join c in lst_invtypes_assets on b.typeID equals c.typeID
join d in lst_stations_composite_retribution on b.locationID equals d.stationID
select new
{b.contents, b.flag, b.itemID, b.locationID, d.solarSystemName, d.security, d.securityClass, d.regionName, b.quantity, b.singleton, b.typeID, c.groupID, c.marketGroupID, c.volume,
c.typeName, c.description};
var lst_assets_root_typeid_station = var_assets_root_typeid_station.ToList(); // Using .ToArray() is about 200ms faster than .ToList()
stopwatch2.Start();
for (Int32 a = 0; a < lst_assets_root_typeid_station.Count(); a++)
{
if (lst_assets_root_typeid_station[a].contents.Count() > 0)
{
for (Int32 z = 0; z < lst_assets_root_typeid_station[a].contents.Count(); z++)
{
foreach (AssetList.Item contentnode in getAllContents(lst_assets_root_typeid_station[a].contents[z]))
{
var var_row_invtypes_assets = lst_invtypes_assets.Where(x => x.typeID == contentnode.typeID).ToArray();
contentnode.groupID = var_row_invtypes_assets[0].groupID;
contentnode.typeName = var_row_invtypes_assets[0].typeName;
contentnode.description = var_row_invtypes_assets[0].description;
contentnode.volume = var_row_invtypes_assets[0].volume;
contentnode.marketGroupID = var_row_invtypes_assets[0].marketGroupID;
}
}
}
}
stopwatch2.Stop();
stopwatch1.Stop();
lbl_stopwatch1.Text = "Everything: " + stopwatch1.Elapsed.ToString("mm'':ss''.ff"); // 1.16 seconds no debugging
lbl_stopwatch2.Text = "contents sublists: " + stopwatch2.Elapsed.ToString("mm'':ss''.ff"); // contents sublists take 0.63 seconds no debugging
}
IEnumerable<AssetList.Item> getAllContents(AssetList.Item contentNode)
{
if (contentNode.contents.Count == 0)
{
yield return contentNode;
}
else
{
foreach (AssetList.Item subContentNode in contentNode.contents)
{
yield return subContentNode;
foreach (AssetList.Item subSubContentNode in getAllContents(subContentNode))
yield return subSubContentNode;
}
}
}
您不是在寻找SelectMany吗?
var contents = lst_invtypes_assets.contents.SelectMany(x => x.contents);
我认为您要访问的是外部.contents
属性,如果它包含任何contents
,那么也要访问这些属性,依此类推…递归。
虽然您可以通过定义一个递归Func<AssetList.Item, IEnumerable<AssetList.Item>>
和一行使用.Aggregate
的LINQ来实现这一点,但定义自己的递归方法可能会更容易/更可读。
IEnumerable<AssetList.Item> getAllContents(AssetList.Item station) {
foreach (AssetList.Item subStation in station.contents) {
yield return subStation;
foreach (AssetList.Item subSubStation in getAllContents(substation))
yield return subSubStation;
}
}
然后你可以做一个简单的foreach(var station in getAllContents(parentStation))
,或者修改它以包括原始站点,使其成为一个扩展方法,等等。