1

I'm reading data from an excel sheet and (after some processing) I'm placing it into a class:

public class Record
{
        public string partNo { get; set; }
        public float quantity { get; set; }
        public string designator { get; set; }
}

This is what the data looks like:

record[0]=new Record { partNo = "123456789", quantity = 2, designator = "C1 C2 " };
record[1]=new Record { partNo = "333333333", quantity = 2, designator = "D1 D2 " };
record[2]=new Record { partNo = "123456789", quantity = 3, designator = "C10 C12 C15 " };
record[3]=new Record { partNo = "222222222", quantity = 5, designator = "Q5 Q6 Q10 Q22 Q50 " };

Is there a way to group the partNo that have the same data and add the quantities and concat the designators? like...

record[0]=new Record { partNo = "123456789", quantity = 5, designator = "C1 C2 C10 C12 C15 " };
record[1]=new Record { partNo = "333333333", quantity = 2, designator = "D1 D2 " };
record[3]=new Record { partNo = "222222222", quantity = 5, designator = "Q5 Q6 Q10 Q22 Q50 " };

I found a similar post but not quite: Group by in LINQ

My c# skills are beginner and my Linq experience is non-existence...lol.

Any help is appreciated. Thanks

ASh
  • 34,632
  • 9
  • 60
  • 82
Rodo
  • 115
  • 3
  • You should follow the C# [Naming Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines#in-this-section). Apart from using the proper casing, one of the Do's and Don'ts reads: *"Do name collection properties with a plural phrase describing the items in the collection instead of using a singular phrase followed by "List" or "Collection"."*. Your array `record` should be `records` to indicate an enumeration to the reader. – BionicCode Oct 15 '21 at 22:37
  • LINQ is for querying so you can use it to transform your initial `record` `List` (or `Record[]`) to a new `List` (or `Record[]`) by using `GroupBy` and `ToList()` or `ToArray()`. – NetMage Oct 15 '21 at 22:41
  • @BionicCode: That was a typo it is actually records. Thanks for the link. – Rodo Oct 15 '21 at 23:09
  • I have updated the answer to show how to assign the result to the records array. – BionicCode Oct 15 '21 at 23:13
  • @BionicCode I think you forgot to update your answer :) – NetMage Oct 15 '21 at 23:29

1 Answers1

1

You can use Enumerable.GroupBy to group and project the elements to a new form:

IEnumerable<Record> groupedRecords = records.GroupBy(
  record => record.partNo, 
  (groupKey, records) => 
    new Record
    { 
      partNo = groupKey, 
      quantity = records.Sum(record => record.quantity), 
      designator = string.Concat(
        records.Select(record => record.designator)) 
    });
BionicCode
  • 1
  • 4
  • 28
  • 44
  • 1
    I would suggest using `String.Concat` makes more sense than `Aggregate`. Also, why use 4 argument `GroupBy` instead of 3 argument? (`Enumerable.GroupBy(keySelector, resultSelector)`)? – NetMage Oct 15 '21 at 22:37
  • StringBuilder is recommended for big strings or a big number of concatenations (see documentation). But I agree, when expecting the source collection to contain many elements String.Concat can add a perfomance improvement. It is more readable for sure. – BionicCode Oct 15 '21 at 22:56
  • It is not an array but I figured it out: records = groupedRecords.ToList(); Thanks. – Rodo Oct 15 '21 at 23:17
  • 1
    @Rodo You don't need to pass in the type: C# infers generic type parameters from passed in parameters, and `groupedRecords` is the first parameter to `ToList` so the compiler knows from `IEnumerable` that the result will be `List`. Just do `.ToList()`. – NetMage Oct 15 '21 at 23:28