Reputation: 15293
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 Cases
s 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:
Id ---------- PalletId
1 ----------- 5
2 ----------- 6
3 ----------- 4
4 ----------- 5
5 ----------- 6
6 ----------- 4
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
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
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