I have a List
and I have the new order in which the List
should have the items in int[]
I want that the item in List
should be re-ordered as per the items in int[]
. Here is my code to do that:
class Program
{
static void Main(string[] args)
{
List<Test> tests = new List<Test>() {
new Test(){ No = 201 },
new Test(){ No = 101 },
new Test(){ No = 300 },
new Test(){ No = 401 },
new Test(){ No = 500 },
new Test(){ No = 601 }
};
int[] newOrder = new int[6] { 201, 401, 300, 101, 601, 500 };
//after the opration the List should contain items in order 201, 401, 300, 101, 601, 500
List<Test> newTests = new List<Test>();
foreach(var order in newOrder)
{
var item = tests.SingleOrDefault(t => t.No == order);
if (item != null)
newTests.Add(item);
}
}
}
This works fine. But it creates a separate List
and performs operation on it. Is there better way where I can use may be built in .Net operation for this or may be perform the operation on the same List
without creating these Temp List
etc?
Thank you.
You need to think about performance when running a sort like this.
If you expect only a handful of elements, then Pedro's solution is OK.
If you expect to have many elements (say, 100's or 1000's), then it's not a good idea to search through entire collection of tests
for each element in newOrder
. In this case, it would be helpful to use a Dictionary
for all index/sort-order lookups. Try something like this:
List<Test> tests = new List<Test>() {
new Test(){ No = 101 },
new Test(){ No = 201 },
new Test(){ No = 300 },
new Test(){ No = 401 },
new Test(){ No = 500 },
new Test(){ No = 601 }
};
int[] newOrder = new int[6] { 201, 401, 300, 101, 601, 500 };
// Create a Dictionary/hashtable so we don't have to search in newOrder repeatedly
// It will look like this: { {201,0}, {401,1}, {300,2}, {101,3}, {601,4}, {500,5} }
Dictionary<int, int> newOrderIndexedMap = Enumerable.Range(0, newOrder.Length - 1).ToDictionary(r => newOrder[r], r => r);
// Order using 1 CPU
var orderedTests = tests.OrderBy(test => newOrderIndexedMap[test.No]);
// Order using multi-threading
var orderedInParallelTests = tests.AsParallel().OrderBy(test => newOrderIndexedMap[test.No]);
// Order using 1 CPU, when it's possible that a match will not be found in newOrder
var orderedTestsSafe = tests.OrderBy(test =>
{
int index;
bool foundIndex = newOrderIndexedMap.TryGetValue(test.No, out index);
return foundIndex ? index : Int32.MaxValue;
});
Note that both this answer and Pedro's assume that newOrder
contains all values contained in the tests
elements and vice versa.
var newTesties= newOrder.Select(o => tests.First(t => t.No == o));
Basically, I'm selecting every number 'o' in newOrder, and using that to pick up the corresponding test. You WILL end up with a new list though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With