C# LINQ NET 3.5 SP1:使用LINQ按两个字段分组并为组中的所有成员分配一个相关的唯一ID(整数)
C# LINQ NET 3.5 SP1: Using LINQ to group by two fields and assigning a correlative unique ID (integer number) to all member of the group
我有一个源列表,其中每个项目都是一个具有 public 属性的 class。
项目Class:
public class Item
{
public DateTime Date
{
get;
set;
}
public string ProviderID
{
get;
set;
}
public List<AnotherClass> listOfitems
{
get;
set;
}
public byte[] Img
{
get;
set;
}
// Other properties
public long GroupID
{
get;
set;
}
}
来源列表例如:
List<Item> mySourceList;
假设 mySourceList 开头如下所示(此处以表格模式表示):
Date | ProviderID | BillID | QuantityToPay | State | GroupID
01/07/2015 9080AB 6453300 2100 Pending 0
20/01/2014 1080ZX 1200000 1500 Pending 0
01/07/2015 9080AB 6454000 1000 Pending 0
23/11/2016 6080AB 7853300 15000 Pending 0
02/10/2015 9080AB 6454100 2000 Pending 0
01/01/2017 2161DV 9200000 500 Pending 0
20/05/2017 8733ZZ 9800153 60000 Pending 0
01/01/2017 2161DV 9200001 21000 Pending 0
01/01/2017 2161DV 9200002 51700 Pending 0
20/05/2017 8733ZZ 9800154 90000 Pending 0
20/04/2017 8733ZZ 9800102 25000 Pending 0
20/06/2017 8733ZZ 9800200 90000 Pending 0
20/04/2017 8733ZZ 9800103 50000 Pending 0
现在我想使用 LINQ 获取另一个列表 myDestList,它按提供者分组,然后按日期字段分组,还按提供者排序,然后按日期排序。
此外,我想为包含超过 1 行的每个组 (Date,ProviderID) 分配一个相关编号 (GroupID)(该编号对于同一组的所有成员应该相同)。仅包含 1 行的组,此相关数字将始终为 0。例如,处理完上面的列表后,我想获得下面的列表 myDestList:
Date | ProviderID | BillID | QuantityToPay | State | GroupID
20/01/2014 1080ZX 1200000 1500 Pending 0
01/01/2017 2161DV 9200000 500 Pending 1
01/01/2017 2161DV 9200001 21000 Pending 1
01/01/2017 2161DV 9200002 51700 Pending 1
23/11/2016 6110FB 7853300 15000 Pending 0
20/04/2017 8733ZZ 9800102 25000 Pending 2
20/04/2017 8733ZZ 9800103 50000 Pending 2
20/05/2017 8733ZZ 9800153 60000 Pending 3
20/05/2017 8733ZZ 9800154 90000 Pending 3
20/06/2017 8733ZZ 9800200 90000 Pending 0
01/07/2015 9080AB 6453300 2100 Pending 4
01/07/2015 9080AB 6454000 1000 Pending 4
02/10/2015 9080AB 6454100 2000 Pending 0
我在下面尝试(没有为每个组分配相关编号,因为我不知道该怎么做):
List<Item> myDestList = mySourceList.GroupBy(x => new { x.ProviderID, x.Date }).Select(grp => grp.ToList<Item>()).ToList<Item>();
如何使用 LINQ 执行此操作?
尝试 #1:
最后我做了以下:
var grp = mySourceList .GroupBy(e => new { e.ProviderID, e.Date });
int groupId = 1;
foreach (var group in grp)
{
int id = group.Count() > 1 ? groupId++ : 0;
// Loop through each item within group
foreach (var item in group)
item.GroupID = id;
}
我假设您不想就地更新项目,而只是需要生成新项目。我也不太明白其他属性或 "AnotherClass" 的作用。因此,这里有一些代码采用 Item 的精简版本(仅 Date、ProviderID 和 GroupID)并为您提供所需的结果。
请注意,分配的 GroupID 不是连续的。
裁减class:
public class Item
{
public DateTime Date { get; set; }
public string ProviderID { get; set; }
public long GroupID { get ; set ; }
}
填充"mySourceList"(不可否认,日期解析有点粗糙并准备就绪):
List<Item> mySourceList = new List<Item>()
{
new Item {Date=DateTime.Parse("01/07/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("20/01/2014"), ProviderID = "1080ZX", GroupID = 0 },
new Item {Date=DateTime.Parse("01/07/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("23/11/2016"), ProviderID = "6080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("02/10/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("20/05/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("20/05/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/04/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/06/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/04/2017"), ProviderID = "8733ZZ", GroupID = 0 },
};
Linq:
var myDestList = mySourceList.OrderBy(i => i.Date).ThenBy(i => i.ProviderID)
.GroupBy(x => new {x.ProviderID, x.Date})
.Select((grp, idx) => new {GroupId = idx+1, GroupCount = grp.Count(), Items = grp})
.SelectMany(newgrp => newgrp.Items.DefaultIfEmpty(), (g, i) => new { Date=i.Date, ProviderID = i.ProviderID, GroupID = (g.GroupCount == 1 ? 0 : g.GroupId)})
.OrderBy(i => i.Date).ThenBy(i=>i.ProviderID)
.ToList();
结果:
{ Date = 20/01/2014 00:00:00, ProviderID = 1080ZX, GroupID = 0 }
{ Date = 01/07/2015 00:00:00, ProviderID = 9080AB, GroupID = 2 }
{ Date = 01/07/2015 00:00:00, ProviderID = 9080AB, GroupID = 2 }
{ Date = 02/10/2015 00:00:00, ProviderID = 9080AB, GroupID = 0 }
{ Date = 23/11/2016 00:00:00, ProviderID = 6080AB, GroupID = 0 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 20/04/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 6 }
{ Date = 20/04/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 6 }
{ Date = 20/05/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 7 }
{ Date = 20/05/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 7 }
{ Date = 20/06/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 0 }
我有一个源列表,其中每个项目都是一个具有 public 属性的 class。
项目Class:
public class Item
{
public DateTime Date
{
get;
set;
}
public string ProviderID
{
get;
set;
}
public List<AnotherClass> listOfitems
{
get;
set;
}
public byte[] Img
{
get;
set;
}
// Other properties
public long GroupID
{
get;
set;
}
}
来源列表例如:
List<Item> mySourceList;
假设 mySourceList 开头如下所示(此处以表格模式表示):
Date | ProviderID | BillID | QuantityToPay | State | GroupID
01/07/2015 9080AB 6453300 2100 Pending 0
20/01/2014 1080ZX 1200000 1500 Pending 0
01/07/2015 9080AB 6454000 1000 Pending 0
23/11/2016 6080AB 7853300 15000 Pending 0
02/10/2015 9080AB 6454100 2000 Pending 0
01/01/2017 2161DV 9200000 500 Pending 0
20/05/2017 8733ZZ 9800153 60000 Pending 0
01/01/2017 2161DV 9200001 21000 Pending 0
01/01/2017 2161DV 9200002 51700 Pending 0
20/05/2017 8733ZZ 9800154 90000 Pending 0
20/04/2017 8733ZZ 9800102 25000 Pending 0
20/06/2017 8733ZZ 9800200 90000 Pending 0
20/04/2017 8733ZZ 9800103 50000 Pending 0
现在我想使用 LINQ 获取另一个列表 myDestList,它按提供者分组,然后按日期字段分组,还按提供者排序,然后按日期排序。 此外,我想为包含超过 1 行的每个组 (Date,ProviderID) 分配一个相关编号 (GroupID)(该编号对于同一组的所有成员应该相同)。仅包含 1 行的组,此相关数字将始终为 0。例如,处理完上面的列表后,我想获得下面的列表 myDestList:
Date | ProviderID | BillID | QuantityToPay | State | GroupID
20/01/2014 1080ZX 1200000 1500 Pending 0
01/01/2017 2161DV 9200000 500 Pending 1
01/01/2017 2161DV 9200001 21000 Pending 1
01/01/2017 2161DV 9200002 51700 Pending 1
23/11/2016 6110FB 7853300 15000 Pending 0
20/04/2017 8733ZZ 9800102 25000 Pending 2
20/04/2017 8733ZZ 9800103 50000 Pending 2
20/05/2017 8733ZZ 9800153 60000 Pending 3
20/05/2017 8733ZZ 9800154 90000 Pending 3
20/06/2017 8733ZZ 9800200 90000 Pending 0
01/07/2015 9080AB 6453300 2100 Pending 4
01/07/2015 9080AB 6454000 1000 Pending 4
02/10/2015 9080AB 6454100 2000 Pending 0
我在下面尝试(没有为每个组分配相关编号,因为我不知道该怎么做):
List<Item> myDestList = mySourceList.GroupBy(x => new { x.ProviderID, x.Date }).Select(grp => grp.ToList<Item>()).ToList<Item>();
如何使用 LINQ 执行此操作?
尝试 #1:
最后我做了以下:
var grp = mySourceList .GroupBy(e => new { e.ProviderID, e.Date });
int groupId = 1;
foreach (var group in grp)
{
int id = group.Count() > 1 ? groupId++ : 0;
// Loop through each item within group
foreach (var item in group)
item.GroupID = id;
}
我假设您不想就地更新项目,而只是需要生成新项目。我也不太明白其他属性或 "AnotherClass" 的作用。因此,这里有一些代码采用 Item 的精简版本(仅 Date、ProviderID 和 GroupID)并为您提供所需的结果。
请注意,分配的 GroupID 不是连续的。
裁减class:
public class Item
{
public DateTime Date { get; set; }
public string ProviderID { get; set; }
public long GroupID { get ; set ; }
}
填充"mySourceList"(不可否认,日期解析有点粗糙并准备就绪):
List<Item> mySourceList = new List<Item>()
{
new Item {Date=DateTime.Parse("01/07/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("20/01/2014"), ProviderID = "1080ZX", GroupID = 0 },
new Item {Date=DateTime.Parse("01/07/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("23/11/2016"), ProviderID = "6080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("02/10/2015"), ProviderID = "9080AB", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("20/05/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("01/01/2017"), ProviderID = "2161DV", GroupID = 0 },
new Item {Date=DateTime.Parse("20/05/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/04/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/06/2017"), ProviderID = "8733ZZ", GroupID = 0 },
new Item {Date=DateTime.Parse("20/04/2017"), ProviderID = "8733ZZ", GroupID = 0 },
};
Linq:
var myDestList = mySourceList.OrderBy(i => i.Date).ThenBy(i => i.ProviderID)
.GroupBy(x => new {x.ProviderID, x.Date})
.Select((grp, idx) => new {GroupId = idx+1, GroupCount = grp.Count(), Items = grp})
.SelectMany(newgrp => newgrp.Items.DefaultIfEmpty(), (g, i) => new { Date=i.Date, ProviderID = i.ProviderID, GroupID = (g.GroupCount == 1 ? 0 : g.GroupId)})
.OrderBy(i => i.Date).ThenBy(i=>i.ProviderID)
.ToList();
结果:
{ Date = 20/01/2014 00:00:00, ProviderID = 1080ZX, GroupID = 0 }
{ Date = 01/07/2015 00:00:00, ProviderID = 9080AB, GroupID = 2 }
{ Date = 01/07/2015 00:00:00, ProviderID = 9080AB, GroupID = 2 }
{ Date = 02/10/2015 00:00:00, ProviderID = 9080AB, GroupID = 0 }
{ Date = 23/11/2016 00:00:00, ProviderID = 6080AB, GroupID = 0 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 01/01/2017 00:00:00, ProviderID = 2161DV, GroupID = 5 }
{ Date = 20/04/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 6 }
{ Date = 20/04/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 6 }
{ Date = 20/05/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 7 }
{ Date = 20/05/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 7 }
{ Date = 20/06/2017 00:00:00, ProviderID = 8733ZZ, GroupID = 0 }