我有一个List
我有一个新订单List
应该包含int[]
中的项目我希望List
中的项目应该重新按照int[]
中的项目排序。这是我的代码:
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);
}
}
}
这很好用。但它会创建一个单独的List
并对其执行操作。有没有更好的方法我可以使用内置的.Net操作或者可以在同一个List
上执行操作而不创建这些Temp List
等?
谢谢。
答案 0 :(得分:6)
在运行这样的类型时,您需要考虑性能。
如果您只想要少数几个元素,那么Pedro's 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'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;
});
请注意,此答案和佩德罗都认为newOrder
包含tests
元素中包含的所有值,反之亦然。
答案 1 :(得分:2)
var newTesties= newOrder.Select(o => tests.First(t => t.No == o));
基本上,我选择每个号码&#39; o&#39;在newOrder中,并使用它来获取相应的测试。你最终会得到一个新的清单。
答案 2 :(得分:2)
使用左连接可以是使用自定义排序的方法之一。对于任何与自定义排序不匹配的项目,请使用从末尾开始的列表的原始顺序
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;
答案 3 :(得分:1)
尝试加入你的数组并像这样列出
newOrder.Join(tests, no => no, tst => tst.No, (no, tst) => tst)