Cole W
Cole W

Reputation: 15293

sorting by using another collection

I have a unique sorting problem in which I have an array of objects that are given to me in "order" but the order is not known to me or sorted on any particular property on the object.

The object is as follows

public class Case
{
    public virtual int Id { get; set; }

    public virtual string PalletId { get; set; }
}

What I need to do is take this array of Casess that I'm given and create a new list of these objects that is sorted by the relative order of the original collections PalletId field then by it's id field. It is not an absolute ordering on this field though because it's relative to the original order of the collection.

For example:

Original Collection

Id ---------- PalletId
1 ----------- 5
2 ----------- 6
3 ----------- 4
4 ----------- 5
5 ----------- 6
6 ----------- 4

Sorted Collection

Id ---------- PalletId
1 ----------- 5
4 ----------- 5
2 ----------- 6
5 ----------- 6
3 ----------- 4
6 ----------- 4

The sorted collection above represents how I need to sort these. Notice how the palletid's in the sorted collection are not in ascending or descending order but they are sorted by the order in which you see them in the original collection (5, 6, 4). Within each pallet id I have to sort the id field in that same order. So it's the order in which I see the Id field in the original collection for a particular pallet id.

Upvotes: 2

Views: 172

Answers (3)

Matthew Watson
Matthew Watson

Reputation: 109547

This gives the correct answer, but it seems a little fiddly!

It gives a different answer from Henk's in the case where the order of the Id values is descending. I think this might be what the OP is wanting, but I'm not entirely sure.

using System;
using System.Collections.Generic;

namespace Demo
{
    class Item
    {
        public int Id;
        public int PalletId;

        public override string ToString()
        {
            return string.Format("{0}, {1}", Id, PalletId);
        }
    }

    class Program
    {
        void run()
        {
            var items = new []
            {
                new Item { Id = 1, PalletId = 5},
                new Item { Id = 2, PalletId = 6},
                new Item { Id = 3, PalletId = 4},
                new Item { Id = 4, PalletId = 5},
                new Item { Id = 5, PalletId = 6},
                new Item { Id = 6, PalletId = 4}
            };

            sortItems(items);
            items.Print();
        }

        void sortItems(Item[] items)
        {
            for (int i = 0, j = 1; i < items.Length && j < items.Length; i = j, j = i + 1)
            {
                while ((j < items.Length) && (items[i].PalletId == items[j].PalletId))
                    ++j;

                for (int k = j+1; k < items.Length; ++k)
                {
                    if (items[k].PalletId == items[i].PalletId)
                    {
                        move(items, j, k);
                        break;
                    }
                }
            }
        }

        void move(Item[] items, int to, int from)
        {
            var temp = items[from];

            for (int i = from; i > to; --i)
                items[i] = items[i-1];

            items[to] = temp;
        }

        static void Main()
        {
            new Program().run();
        }
    }

    static class DemoUtil
    {
        public static void Print(this object self)
        {
            Console.WriteLine(self);
        }

        public static void Print(this string self)
        {
            Console.WriteLine(self);
        }

        public static void Print<T>(this IEnumerable<T> self)
        {
            foreach (var item in self) Console.WriteLine(item);
        }
    }
}

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273179

After the clarification, a simple GroupBy + SelectMany seems to do the trick:

var sortedCases = originalCases
    .GroupBy(c => c.PalletId)
    .SelectMany(g => g.OrderBy(c => c.Id)) ;

As GroupBy() preserves the initial order of the keys according to this SO answer.

Upvotes: 4

Dave Zych
Dave Zych

Reputation: 21887

Use OrderBy

var orderedCases = Cases.OrderByDescending(c => c.PalletId).ThenBy(c => c.Id);

Upvotes: 3

Related Questions