List of orders for a specific order

I have List, and I have a new order in which the Listelements in should be int[], I want the element in to Listbe reordered according to the elements in int[]. Here is my code:

   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);
            }


        }

    }

It works great. But he creates a separate one Listand performs an operation on it. Is there a better way that I can use it that can be built into the .Net operation for this, or can perform the operation on the same Listwithout creating these Temp List, etc.?

Thank.

+4
source share
4 answers

You need to think about performance when starting this type.

, Pedro solution .

(, 100 1000), tests newOrder. Dictionary /. - :

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 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;
    });

, , newOrder , tests .

+5
var newTesties= newOrder.Select(o => tests.First(t => t.No == o));

, "o" newOrder , . .

+1

newOrder.Join(tests, no => no, tst => tst.No, (no, tst) => tst)
+1

Using a left connection can be one way to use a custom order. For any item that does not match the customized order, use the original list order, starting at the end

var results = from a in tests.Select((r, i) => new {item = r, Index = i})
              // left join
              from b in newOrder.Select((r, i) => new { item = r, Index = i })
                                .Where(b => a.item.No == b.item).DefaultIfEmpty() 
              // Not in order list then use original ordering
              orderby (b == null ? tests.Count() + a.Index : b.Index) 
              select a.item;

.NET Fiddle

+1
source

All Articles