-1

Example is here, should work in online compilers:

internal class Program
    {
        static void Main(string[] args)
        {
            var i1 = new Item();
            i1.Val1 = 1;
            i1.Val2 = 2.1;

            var i2 = new Item();
            i2.Val1 = 1;
            i2.Val2 = 1.5;

            var i3 = new Item();
            i3.Val1 = 3;
            i3.Val2 = 0.3;

            var list = new List<Item>
            {
                i1,
                i2,
                i3
            };
            var grouped = list.GroupBy(x => x.Val1);

            Program p = new Program();
            foreach(var group in grouped)
                p.Func(group);
            
        }

        public void Func(IGrouping<int, Item> list)
        {
            list.OrderBy(x => x.Val2); //list will be ordered, but not saved
            list = (IGrouping<int, Item>)list.OrderBy(x => x.Val2); //exception
        }
    }

    public class Item
    {
        public int Val1 { get; set; }
        public double Val2 { get; set; }
    }

It's simplified code of what I'm trying to do - I need to order list inside Func, but I have no idea how. First line works in theory, but since it's not a void it's not working in practice - list is not actually ordered.

Second line should work, actually Visual Studio suggested that, but it throws runtime exception - Unable to cast object of type System.Linq.OrderedEnumerable to System.Linq.IGrouping.

I'm out of ideas for the time being, but there is no way of bypassing it - I absolutely need to order it there.

Edit

My current solution is to use Select(x => x) to flatten the IGrouping to normal List, this way I can easily order it and edit values without losing reference to grouped. If you really want to keep IGrouping then you are out of luck, does not seem to be possible.

  • Does this answer your question? [How to order IGrouping without changing its type?](https://stackoverflow.com/questions/31287126/how-to-order-igrouping-without-changing-its-type) – 41686d6564 stands w. Palestine Nov 12 '22 at 17:34
  • @41686d6564standsw.Palestine I have found it before posting this question, provided code contains errors and doesn't compile. Still no ideas on my end, if I won't solve it I guess it's time to change the job. –  Nov 12 '22 at 17:45
  • @CorporalGiraffe I edited the code in Jon's answer. I think it was written in a hurry but the idea is still correct. Anyway, it should compile and work fine now. – 41686d6564 stands w. Palestine Nov 12 '22 at 18:08
  • @41686d6564standsw.Palestine Still doesn't compile. `Compilation error (line 75, col 9): Using the generic type 'System.Collections.Generic.IEnumerator' requires 1 type arguments` –  Nov 12 '22 at 18:15
  • @CorporalGiraffe Maybe because you're missing a `using System.Collections;`? – 41686d6564 stands w. Palestine Nov 12 '22 at 18:23
  • @41686d6564standsw.Palestine doesn't seem to be the case. Still 10 errors. –  Nov 12 '22 at 20:28
  • Well, I can't say for sure what the problem is because you didn't mention what errors you're getting. You do realize that the method returns a _new_ instance of `IGrouping` and that you'd have to change the signature of your `Func` method to also return that object and replace the `IGrouping` item in `grouped`, right? You can't simply copy and paste any piece of code you find on Stack Overflow as is and expect it to work. You should make the necessary adjustments to fit your use case. That being said, here's a complete, working example: https://rextester.com/UDDQFO96458 – 41686d6564 stands w. Palestine Nov 12 '22 at 20:39

3 Answers3

0

Try this.

 var grouped = list.GroupBy(x => x.Val1).Select(a=> a.OrderBy(a=>a.Val2).ToList());

OrderBy returns IOrderedEnumerable you can't cast that to IGrouping

ShubhamWagh
  • 565
  • 2
  • 9
  • This way I probably can't iterate through groups, and it doesn't compile so I can't be sure. –  Nov 12 '22 at 18:15
  • What are you expecting in the output? Group or List? Can you provide more detail about that? – ShubhamWagh Nov 12 '22 at 18:26
  • Output is void, because I want to change values inside IGrouping, it's a reference to list from main. It looks like simple .Select(x => x) in my case will work because it will flatten the Grouping without losing reference. –  Nov 12 '22 at 20:26
0

Your example code doesn't show what you are trying to arrive at.

list.OrderBy(x => x.Val2); //list will be ordered, but not saved

OrderBy doesn't order the existing collection in-place. It effectively returns a new collection.

list = (IGrouping<int, Item>)list.OrderBy(x => x.Val2); //exception

OrderBy returns an IOrderedEnumerable<TElement>. Both IOrderedEnumerable<TElement> and IGrouping<TKey,TElement> derive from IEnumerable<TElement> but you can't cast an IOrderedEnumerable to an IGrouping.

If all you want is to write out the values, then Func could be:

        public IEnumerable<Item> Func(IGrouping<int, Item> list)
        {
            return list.OrderBy(x => x.Val2);
        }

and the foreach loop could be:

            foreach(var group in grouped)
            {
                var orderedList = p.Func(group);
                Console.WriteLine($"group: {group.Key}");
                foreach (var value in orderedList)
                {
                    Console.WriteLine($" {value.Val2}");
                }
            }

Hopefully this helps.

Jonathan Dodds
  • 2,654
  • 1
  • 10
  • 14
  • 2
    _"OrderBy returns a new list."_ - no, it does not. – Guru Stron Nov 12 '22 at 18:00
  • I appreciate the help but I need ordered IGrouping, as I stated in question, this cannot be bypassed in any way. –  Nov 12 '22 at 18:17
  • @CorporalGiraffe Your question doesn't state that. – Jonathan Dodds Nov 13 '22 at 01:44
  • @JonathanDodds looks like you didn't read it in it's entirety. –  Nov 15 '22 at 12:18
  • @GuruStron When you commented "no, it does not.", I assume you mean that I loosely used the word 'list' when the return is actually a derived type of `IEnumerable`. I edited my answer to read "`OrderBy` doesn't order the existing collection in-place. It effectively returns a new collection." Does that address your comment? – Jonathan Dodds Nov 15 '22 at 12:59
0

Use First method at the end in order to get IGrouping collection of ordered items.

public void Func(IGrouping<int, Item> list)
{
   list = list.OrderBy(x => x.Val2).GroupBy(x => x.Val1).First(); 
}
Bronek
  • 19
  • 2