skip to Main Content

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.

3

Answers


  1. 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

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
  3. 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(); 
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search