0

I have an object of objects where one property can have duplicate values i am trying to find an algorithm to loop through the object and create a new list of object having group by duplicate values.

how do i loop through an object and create a new object in C# i have a view model eg:

   pViewModel  {
    public itemFullName {get;set;}
    public Item Item{get;set;}
    public string itemAddress {get;set;}
    public string itemCountry {get;set;}
public string addressId {get;set;}
    }
    public Item{
    public int itemId{get;set;}
    }

I want to create a new object after finding matching fullname but different id so my new object will have a list of itemFullName, item.itemid(pipedelimited values for all the items in the previous list),itemaddress, itemCountry in it.

Any help will be awesome. thank you

someone pointed out to this

var itemsAndIds = list
    .GroupBy(m => m.itemFullName, m => m.Item.itemId)
    .Select(g => new {ItemFullName = g.Key, ItemIds = string.Join("|", g)})

but now I need the new properties added to this object

  • Is ItemAddress and ItemCountry are same for grouped itemid or different. IF different then how should they be selected in new object ? – Mahesh Jul 18 '19 at 10:24
  • they are the same for all duplicate values – user1098924 Jul 18 '19 at 10:25
  • if there is a property that is different for the above list eg. addressId , how to return in the grouped by list with comma separated values? – user1098924 Aug 07 '19 at 18:36

2 Answers2

1

This answer could help you: https://stackoverflow.com/a/5232194/1341189

Given that ItemAddress and ItemCountry are always the same as ItemFullName in your example that means you can do something like this:

var itemsAndIds = list
    .GroupBy(m => new { 
               ItemFullName = m.itemFullName, 
               ItemAddress = m.itemAddress, 
               ItemCoutnry = m.itemCountry },
             m => m.Item.itemId)
    .Select(g => new {
              ItemFullName = g.Key.ItemFullName, 
              ItemIds = string.Join("|", g),
              ItemAddress = g.Key.ItemAddress,
              ItemCoutnry = g.Key.ItemCountry})

Also I would like to suggest that you read the Microsoft Naming Conventions.

Property Names should be written in PascalCase (same goes for Class Names). https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members

Hightower
  • 66
  • 1
  • 4
  • if there is a property that is different for the above list eg. addressId , how to return in the grouped by list with comma separated values? – user1098924 Aug 07 '19 at 18:36
  • @user1098924 you can also include more properties in the second part of the groupBy like this: `m => new { ItemId = m.Item.itemId, AddressId = m.addressId }` then you have to use them like this: `ItemIds = string.Join("|", g.Select(gs => gs.ItemId)), AddressIds = string.Join("|", g.Select(gs => gs.AddressId).Distinct()),` PS: use Distinct if you only want to get distinct adress ids in your separated list of address ids – Hightower Aug 08 '19 at 13:02
0

You could override bool Equals(Object obj) method in your object. This way you can group by whole items and then just select new ones. You will keep your comparation logic sealed in your object, co you can easily use build in mechanics like == comparation or whole linq magic without need of any hacks. this way your class is fully compatible with SOLID principle

keep in mind that to preserve consistency if you override Equals, it is also worth to override int GetHashCode() method. this way you keep consistency of comparartion (to be precised you need to be sure that tour implementation follows those three main rules):

  • a == a and a.Equals(a) should always be true (Reflexivity).
  • a == b, b == a, a.Equals(b) and b.Equals(a) should always give the same result. (Symmetry)
  • If a == b is true and b == c is true, then a == c should also be true (Transitivity). The same applies to a.Equals(b), b.Equals(c) and a.Equals(c).
Misiakw
  • 902
  • 8
  • 28