I need to count the occurrences of each element in the "ID" field of a generic list. The result should be the list with an added field called "Quantity".
Suppose the following class is used for the list:
public class InfoList
{
public string ID { get; set; }
public DateTime PurchaseDate { get; set; }
public double Amount { get; set; }
public int Quantity { get; set; }
}
Imagine an initial list like the following:
ID | Purchase date | Amount (USD) |
---|---|---|
DDD | 30 jul 2025 | 258,225.11 |
AXC | 10 nov 2023 | 982,383.95 |
AXC | 12 feb 2031 | -439,130.87 |
TPV | 05 mar 2023 | 439,715.32 |
DDD | 8 apr 2024 | -153,893.38 |
KYR | 24 mar 2023 | -153,893.38 |
AXC | 10 sep 2026 | 638,031.66 |
SPM | 26 oct 2023 | -401,815.59 |
DDD | 08 mar 2023 | -315,099.43 |
HGP | 30 nov 2025 | -474,749.80 |
DDD | 02 jul 2024 | -253,726.59 |
NDS | 06 sep 2029 | 490,035.01 |
HGP | 24 dec 2026 | 468,006.38 |
The final result should be the following:
ID | Purchase date | Amount (USD) | Quantity |
---|---|---|---|
DDD | 30 jul 2025 | 258,225.11 | 4 |
AXC | 10 nov 2023 | 982,383.95 | 3 |
AXC | 12 feb 2031 | -439,130.87 | 3 |
TPV | 05 mar 2023 | 439,715.32 | 1 |
DDD | 8 apr 2024 | -153,893.38 | 4 |
KYR | 24 mar 2023 | -153,893.38 | 1 |
AXC | 10 sep 2026 | 638,031.66 | 3 |
SPM | 26 oct 2023 | -401,815.59 | 1 |
DDD | 08 mar 2023 | -315,099.43 | 4 |
HGP | 30 nov 2025 | -474,749.80 | 2 |
DDD | 02 jul 2024 | -253,726.59 | 4 |
NDS | 06 sep 2029 | 490,035.01 | 1 |
HGP | 24 dec 2026 | 468,006.38 | 2 |
Result should be of type "InfoList" not in a different list or variable.
CodePudding user response:
If I'm understanding this correctly, you can track quantities in a dictionary as a separate data structure.
void main()
{
List<ItemList> purchaseList = buildItemList();
Dictionary<string,int> quantity = buildQuantityDictionary(purchaseList);
printTable(purchaseList, quantity);
}
List<ItemList> buildItemList()
{
//however you build the itemlist
}
Dictionary<string,int> buildQuantityDictionary(List<ItemList> purchaseList)
{
Dictionary<string,int> quantity = new Dictionary<string,int>();
foreach(ItemList item in purchaseList)
{
if(!quantity.ContainsKey(item.id))
{
quantity.add(item.id,0);
}
quantity[item.id] ;
}
return quantity;
}
void printTable(List<ItemList> purchaseList, Dictionary<string,int> quantity)
{
foreach(ItemList item in purchaseList)
{
//You'll need to write a ToString() override for your ItemList object.
Console.WriteLine($"{item.ToString()},{quantity[item.id]}");
}
}
CodePudding user response:
Here's an approach that preserves the original order of the list.
var initial = new[]
{
new { ID = "DDD", PurchaseDate = DateTime.Parse("30 jul 2025"), Amount = 258225.11 },
new { ID = "AXC", PurchaseDate = DateTime.Parse("10 nov 2023"), Amount = 982383.95 },
new { ID = "AXC", PurchaseDate = DateTime.Parse("12 feb 2031"), Amount = -439130.87 },
new { ID = "TPV", PurchaseDate = DateTime.Parse("05 mar 2023"), Amount = 439715.32 },
new { ID = "DDD", PurchaseDate = DateTime.Parse("8 apr 2024"), Amount = -153893.38 },
new { ID = "KYR", PurchaseDate = DateTime.Parse("24 mar 2023"), Amount = -153893.38 },
new { ID = "AXC", PurchaseDate = DateTime.Parse("10 sep 2026"), Amount = 638031.66 },
new { ID = "SPM", PurchaseDate = DateTime.Parse("26 oct 2023"), Amount = -401815.59 },
new { ID = "DDD", PurchaseDate = DateTime.Parse("08 mar 2023"), Amount = -315099.43 },
new { ID = "HGP", PurchaseDate = DateTime.Parse("30 nov 2025"), Amount = -474749.80 },
new { ID = "DDD", PurchaseDate = DateTime.Parse("02 jul 2024"), Amount = -253726.59 },
new { ID = "NDS", PurchaseDate = DateTime.Parse("06 sep 2029"), Amount = 490035.01 },
new { ID = "HGP", PurchaseDate = DateTime.Parse("24 dec 2026"), Amount = 468006.38 },
};
var lookup = initial.ToLookup(x => x.ID);
InfoList[] final =
initial
.Select(i =>
new InfoList()
{
ID = i.ID,
PurchaseDate = i.PurchaseDate,
Amount = i.Amount,
Quantity = lookup[i.ID].Count(),
})
.ToArray();
That gives:
If preserving the initial order isn't important then this works:
InfoList[] final =
(
from i in initial
group i by i.ID into gis
from gi in gis
select new InfoList()
{
ID = gi.ID,
PurchaseDate = gi.PurchaseDate,
Amount = gi.Amount,
Quantity = gis.Count(),
}
).ToArray();