1

I am having a struct as

public struct structMailJob
{
 public string ID;
 public string MailID;
 public int ResendCount;
 public int PageCount;
}

and a list as

List<structMailJob> myStructList = new List<structMailJob>();

I have loaded data in myStructList from database and want myStructList data in a new list after grouping by MailID and ResendCount.

I am trying as:

List<structMailJob> newStructList = new List<structMailJob>();

newStructList = myStructList.GroupBy(u => u.MailID, u=>u.ResendCount)
                                  .Select(grp => new { myStructList = grp.ToList() })
                                  .ToList();

but unable to do that as getting error message - cant implicitly convert generic list to structMailJob.

Kumar Gaurav
  • 899
  • 5
  • 19
  • 35
  • Please go to this [link](http://stackoverflow.com/questions/847066/group-by-multiple-columns) – Devansh Nigam - SA Sep 24 '16 at 06:24
  • use var variable and check the query.check weather it is a type error@gaurav – MMM Sep 24 '16 at 06:25
  • The 'grp => new { myStructList = grp.ToList() }' statement creates an anonymous object whose sole property is a list named myStructList. This type will be the resulting collection's item, Whereas you expect a collection of your specific type. The collection types do not match, hence the exception.
    I would gladly help you achieve your cause if you tell me what it is you want to do with the data.. there are a couple of ways to go about this which depend on the use case..
    – Eyal Perry Sep 24 '16 at 06:27

4 Answers4

2

I think that you are looking for is the following:

var newStructList = myStructList.GroupBy(smj => new { smj.MailID, smj.ResendCount })
                                .Select(grp => new 
                                { 
                                    MailID = grp.Key.MailID,
                                    ResendCount = grp.Key.ResendCount
                                    MailJobs = grp.Select(x=>new 
                                               {
                                                   x.ID,
                                                   x.PageCount
                                               }).ToList() 
                                })
                                .ToList();

Note that we changed the GroupBy clause to the following one:

GroupBy(smj => new { smj.MailID, smj.ResendCount })

Doing so, the key on which the groups would be created would be consisted of both MailID and ResendCount. By the way the former GroupBy clause isn't correct.

Then having done the grouping, we project each group to an object with three properties, MailID and ResendCout, which are the components of the key and list of anonymous type object with two properties, ID and PageCount, which we gave it the name MailJobs.

Last but not least you will notice that I didn't mention the following

List<structMailJob> newStructList = new List<structMailJob>();

I just used the var and declared the newStructList. I don't think that you stated in your post makes sense. How do we expect to get a list of the same objects after grouping them? So I assumed that you might want is the above.

However, I thought you might want also something like this and you didn't want to refer to Grouping.

myStructList = myStructList.OrderBy(smj => smj.MailID)
                           .ThenBy(smj => smj.ResendCount)
                           .ToList();
Christos
  • 53,228
  • 8
  • 76
  • 108
  • Appreciate your help, in your first solution there is small typo i guess, have added smj. as new { smj.MailID, smj.ResendCount } and comma after ResendCount = grp.Key.ResendCount, – Kumar Gaurav Sep 24 '16 at 07:24
1

Linq Query is completely incorrect, following are the important points:

myStructList.GroupBy(u => u.MailID, u=>u.ResendCount) // Incorrect grouping

myStructList.GroupBy(u => new {u.MailID, u.ResendCount }) // Correct grouping, which will do by two columns MailID and ResendCount, last one was only doing by MailID and was using ResendCount for result projection

Now the result is of type IEnumerable<IGrouping<AnonymousType,structMailJob>>, so when you do something like Select, it will end up creating Concatenated List of type IEnumerable<List<structMailJob>> (Removed the assignment to myStructList inside the Select, as that was not correct):

.Select(grp => grp.ToList())

Correct code would require you to flatten using SelectMany as follows:

newStructList = myStructList.GroupBy(u => new {u.MailID, u.ResendCount})
                                      .SelectMany(grp => grp.ToList()).ToList();

Assign it to newStructList, but this code has little use, since literally newStructList is exactly same as myStructList post flattening, ideally you shall be able to use the grouping, so that you can get a subset and thus the correct result, however that depends on your business logic

Mrinal Kamboj
  • 11,300
  • 5
  • 40
  • 74
0

I don't know if I got your question right but it seems to me you missed the 'Group by' signature.

List<structMailJob> myStructList = new List<structMailJob>();

List<structMailJob> newStructList = new List<structMailJob>();

newStructList = myStructList
    // .GroupBy(/*Key Selector */u => u.MailID, /*Element Selector*/u=>u.ResendCount)           
    .GroupBy(u => new { u.MailID, u.ResendCount }) // broup by MailID, ResendCount
    // Note no Element Selector , the 'STRUCT' is 'SELECTED'
    .Select(grp => {
        // NOte: Key ==  Anonymous {MailID, ResendCount } 
        return grp;
    })
    // otherwise you get a IEnumerable<IEnumerable<T>> instead of IEnumerable<T> because you grouped it
    .SelectMany(x=>x)
    .ToList();  
Dan
  • 2,818
  • 23
  • 21
0

If Mrinal Kamboj's answer is what you are looking for, then you could use the following as an alternative:

  var orderedList = myStructList.OrderBy(x => x.MailID).ThenBy(x => x.ResendCount);