Access items in list pertaining to GroupBy() item - c#

I am instantiating a List, derived from an ObservableCollection:
var paidTrips = PaidTrips
.GroupBy(p => new {p.LicenseHolderID})
.ToList();
Which, through a foreach loop, gives me access to the various distinct values in LicenseHolderID.
foreach (var licenseHolder in paidTrips) {
// accessing the string value of LicenseHolderID
// but no access to the other items
}
What I need help with:
How can I obtain access to the other items in paidTrips, which pertain to LicenseHolderID? (Why: I am creating invoices, one per LicenseHolderID, and I am building the invoice with the data from all the other collection properties).
To give some context, here's the full collection I am working with:
PaidTrips.Add(new PaidTrip {
LicenseHolderID = dr[0].ToString(),
VehicleID = dr[1].ToString(),
Year = dr[2].ToString(),
Month = dr[3].ToString(),
Payment = (decimal)dr[4],
PaymentNet = (decimal)dr[5],
OrderFee = (decimal)dr[6],
PaymentFee = (decimal)dr[7],
TripVATcode = (decimal)dr[8],
LicenseHolderInvoiceID = dr[9].ToString(),
TripFeeNet = (decimal)dr[10],
TripFeeVATcode = (decimal)dr[11],
RidelRegionInvoiceID = dr[12].ToString(),
});

It does depend what your looking to do with the data for each invoice? are you looking to summarise the data within each LicenseHolderID group?
var PaidTrips = new List<PaidTrip>();
var paidTrips = PaidTrips
.GroupBy(p => new { p.LicenseHolderID })
.ToList();
foreach (var group in paidTrips)
{
var licenseHolderID = group.Key.LicenseHolderID;
//ie here total payment (This sums all payments for this LicenseHolderID)
var totalPayment = group.Sum(x => x.Payment)
// count of payments made (This Counts all Payments greater than 0)
var totalPayments = group.Count(x => x.Payment > 0)
//Use variables in your invoice generation
}
or as above iterate through each group item and access it in singular form.

If I understand you correctly, you want to access each group member's property. To achieve this, you should use nested foreach to traverse each group and access its members.
var PaidTrips = new List<PaidTrip>();
var paidTrips = PaidTrips
.GroupBy(p => new { p.LicenseHolderID })
.ToList();
foreach (var group in paidTrips)
{
var licenseHolderID = group.Key.LicenseHolderID;
foreach (var paidTrip in group.ToList())
{
Console.WriteLine(paidTrip.TripFeeNet);
}
}

foreach (var licenseHolder in paidTrips) {
// accessing the string value of LicenseHolderID
if (licenseHolder.Key == desiredLicenseHolderID){
foreach (var paidItem in licenseHolder){
paidItem.VehicleID = .......
}
}
}
The .GrouBy() Returns a IGrouping object which contains the Key and the elements grouped by the key. To access the elements of the Key grouping you are after once you iterated through the items and found the one, you can simply iterate through the item as an array.

Related

GROUP BY to List<> with Linq

I'm new to using Linq so I don't understand some things or its syntax. I want to group a list and then loop through it with foreach, like my logic below. Obviously my logic doesn't work.
My code:
var final = finalv.Union(finalc);
final = final.GroupBy(x => x.Clave);
foreach (var articulo in final)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articulo.ArtID;
articulo2.Clave = articulo.Clave;
articulo2.ClaveAlterna = articulo.ClaveAlterna;
lista.Add(articulo2);
}
First, such usage is syntactically consistent with this overloaded method of GroupBy: GroupBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>), and it will return a IEnumerable<IGrouping<TKey,TSource>> variable.
That means, if you run final.GroupBy(x => x.Clave), let's assume he returns finalWithGrouped, then finalWithGrouped.Key is the key and finalWithGrouped.ToList() is a collection of all variables with the same key(at here, it is with the same Clave).
And for your code, try this:
var final = finalv.Union(finalc);
var finalWithGrouped = final.GroupBy(x => x.Clave);
foreach (var articulosWithSameClavePair in finalWithGrouped)
{
var clave = articulosWithSameClavePair.Key;
var articulos = articulosWithSameClavePair.ToList();
foreach(var articulo in articulos)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articulo.ArtID;
articulo2.Clave = articulo.Clave;
articulo2.ClaveAlterna = articulo.ClaveAlterna;
lista.Add(articulo2);
}
}
I suggest you read some examples of using GroupBy.
When you group a list, it will return a key and groued list and you are trying reach a single property of a list.
When you group an data, you can convert it to dictionary, It is not nessesary but better way for me. You can try this code:
var final = finalv.Union(finalc);
final = final.GroupBy(x => x.Clave).ToDictionary(s=> s.Key, s=> s.ToList();
foreach (var articulo in final)
{
foreach (var articuloItem in articulo.value)
{
Articulo articulo2 = new Articulo();
articulo2.ArtID = articuloItem.ArtID;
articulo2.Clave = articuloItem.Clave;
articulo2.ClaveAlterna = articuloItem.ClaveAlterna;
lista.Add(articulo2);
}
}

Sorting a list if internal list is empty

I have a list inside of another list. I need to add to the list only those elements whose internal list is not empty. The data is pulled from the server. The code contains 4 lists, Each inside of another - Companies - Shops - Campaigns - Coupons. I need to check if the Coupons list is not empty and add the elements related to that. I would be very thankfull if someone could help with that.
foreach (var row in Companies)
{
reportData.companies.Add(new Companies { ID = row.Id, name = row.BrandName });
var Shops = logicService.CompanyShopService.GetShopsByCompany(row.Id);
var Campaigns = logicService.CampaignService.GetCampaignsByCompany(row.Id);
foreach (var shop in Shops)
{
reportData.companies.Where(item => item.ID == shop.ClientID).FirstOrDefault().shops.Add(new Distribution_Shops { Id = shop.Id, Name = shop.Name });
var shop_campaigns = Campaigns.Where(item => item.ShopID == shop.Id);
foreach (var campaign in shop_campaigns)
{
var coupons = logicService.CouponsService.GetAllByCampaign(campaign.Id, false);
foreach (var company in reportData.companies)
{
foreach (var tmp_shop in company.shops)
{
if (tmp_shop.Id == shop.Id)
{
tmp_shop.campaigns.Add(new Distribution_Campaign { Id = campaign.Id, Name = campaign.CampaignName, coupons = coupons});
}
}
}
}
}
}

How can I create a list inside a list with a foreach in c# ?

In other words I need all the elements of list "Categories" to be the "Parent" and elements of list "commodities" be the children.
Example
public string GetCommodities()
{
List<dynamic> categories = new List<dynamic>();
List<dynamic> commodities = new List<dynamic>();
foreach (var comcat in QuickQuoteRepo.CommodityCategories.All().OrderBy(o => o.Order))
{
categories.Add(new
{
comcat.Category,
});
foreach (var com in comcat.Commodities.OrderBy(o => o.Name))
{
commodities.Add(new
{
com.Name,
});
}
}
var response = new JavaScriptSerializer().Serialize(commodities);
return response;
}
And see if it's possible to all commodities names inside each category, within this foreach.
I tried adding a dynamic list such as:
dynamic listOfElements = new { CAT = categories, COMM = commodities };
But it does't return elemnts as parents or dependency of categories. Is the same as adding
commodities.Add(new
{
comcat.Category,
com.Name,
});
public string GetCommodities()
{
List<dynamic> categoryCommodityList = new List<dynamic>();
foreach (var comcat in QuickQuoteRepo.CommodityCategories.All().OrderBy(o => o.Order))
{
var allCommodities = comcat.Commodities.OrderBy(o => o.Name).Select(com => com.Name).ToList();
categoryCommodityList.Add(new { Catagory = comcat.Category, Items = allCommodities } );
}
return new JavaScriptSerializer().Serialize(categoryCommodityList);
}
You class structure does not support parent-child relationships. I mean, if what you want is that each Category holds a list of commodities, then you would need something like this:
var result = from c in comcat
select new { Category = c, Commoddities = c.Commoddities};
This will return a hierarchy of Categories including all Commodities underneath it.
If you are just receiving a flat data set, then you need something like this:
var result = from c in comcat
select new { Category = c,
Commoddities = c.Where(x=>x.Category.Name == c.Name).Select(x=>x.Commodity) };
Hopefully you get the idea...

look for inner array ID ,sort it and loop outer array with the sorted ID

I have below code and there is reviewoutocme.ID which is unique identifier. how ever, We do not receive this in order. but I would like to sort all the requests in order based on this ID.
i.e. I want to look for reviewoutocme.ID and when reviewoutocme.ID=1, then loop RequestDetailsType Request first and so on..
how can I do that?
can we do something like that?
IList< ServiceReference2.service> serviceList = new List< ServiceReference2.service>();
foreach (RequestDetailsType Request in PatientRequest.Request.RequestDetailsList)
{
if (Request.ReviewOutcomes != null && Request.ReviewOutcomes .Length > 0)
{
foreach (ReviewOutcomeType reviewoutocme in Request.ReviewOutcomes)
{
var status = reviewoutocme.status.Value;
var dateofservice = reviewoutocme.fromDate;
ServiceReference2.service service = new ServiceReference2.service();
service.sequence=reviewoutocme.ID;
service.InitialReferralTemplate = Request.initialRequestFlag;
service.TotalUnits = Convert.ToInt32(Request.units);
service.DateOfService = dateofservice;
service.Status = status;
service.Sequence = Convert.ToInt32(Request.requestItemDetailSequence);
service.ServiceCategory = "REV";
serviceList.Add(service);
}
}
}
modify you code above as
IList< ServiceReference2.service> serviceList = new List< ServiceReference2.service>();
var lstSortedRequest = PatientRequest.Request.RequestDetailsList.OrderBy(x => x.ReviewOutcomes.Select(y => y.ReviewOutcomeType.Id)).ThenBy(x => x.RequestDetailType).ToList();
foreach (var Request in lstSortedRequest)
{
//process the request as you do in your question.
}
default ordering sequence is Ascending.
My rep is too low to comment.
Try:
var sortedList = reviewoutocme.OrderBy(x => x.ID).ToList();

querying existing ListView items with LINQ

The ListView I have populates through these loops resulting in four columns being filled
// Create a ResXResourceReader
ResXResourceReader rdr0 = new ResXResourceReader(textPath1.Text + ".resx");
ResXResourceReader rdr1 = new ResXResourceReader(textPath1.Text + ".es.resx");
ResXResourceReader rdr2 = new ResXResourceReader(textPath1.Text + ".fr.resx");
foreach (DictionaryEntry d in rdr0)
{
TransResource x = new TransResource();
x.id = d.Key.ToString();
x.en = d.Value.ToString();
resources.Add(x.id, x);
}
foreach (DictionaryEntry d in rdr1)
{
TransResource x = resources[d.Key.ToString()];
x.fr = d.Value.ToString();
}
foreach (DictionaryEntry d in rdr2)
{
TransResource x = resources[d.Key.ToString()];
x.es = d.Value.ToString();
}
foreach (TransResource x in resources.Values)
{
string[] row = { x.id, x.en, x.fr, x.es };
var listViewItem = new ListViewItem(row);
listResx.Items.Add(listViewItem);
}
What I want to do is query all of the results in this ListView against what is entered in textboxQuery. If any field in the entire listview contains the string from textboxQuery I want it to be displayed in a new listview (lets say listviewQueryresult). I've had many failed attempts at this but I know it is possible through LINQ.
Because ListView.Items implements IEnumerable, but does not implement IEnumerable<T> you have to cast it to IEnumerable<ListViewItem> first, to query it using LINQ to Objects:
var results = listResx.Items.Cast<ListViewItem>()
.Where(x => YourPredicate(x));
If any field in the entire listview contains the string from
textboxQuery I want it to then be displayed in a new listview (lets
say listviewQueryresult)
For that, the predicate would be just:
var results = listResx.Items.Cast<ListViewItem>()
.Where(x => x.Text.Contains(textboxQuery));

Categories

Resources