C# 排序列表的首选方式是什么<;T>;根据多种标准?
我有一个内存列表,其中包含大约100万条记录,有多列(日期、名称、值、Id等) 我的问题:对如此大的列表进行多列排序的最佳解决方案(即提供最佳性能)是什么 示例(伪代码):C# 排序列表的首选方式是什么<;T>;根据多种标准?,c#,C#,我有一个内存列表,其中包含大约100万条记录,有多列(日期、名称、值、Id等) 我的问题:对如此大的列表进行多列排序的最佳解决方案(即提供最佳性能)是什么 示例(伪代码): 原则上,有两种方法可以对通用列表进行排序: 使用Linq方法链: var orderedEnumerable = list.OrderByDescending(item => item.Property0) .ThenBy(item => item.Property1) .ThenBy(item
原则上,有两种方法可以对通用列表进行排序:
- 使用Linq方法链:
var orderedEnumerable = list.OrderByDescending(item => item.Property0) .ThenBy(item => item.Property1) .ThenBy(item => item.Property2);
- 使用自定义比较器实现
。使用比较器,您可以创建一个新的有序枚举IComparer
或者,您可以使用var orderedEnumerable = list.OrderBy(item => item, new MyComparer());
方法就地排序:sort()
list.Sort(new MyComparer());
List.Sort(IComparer)
原则上运行得最快,但这完全取决于是否要枚举Enumerable.OrderBy的整个结果)
下面是一个简单的基准测试示例:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
class Record
{
public string Name { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
}
class RecordComparer : IComparer<Record>
{
public int Compare(Record x, Record y)
{
// Sort by Name, Age, and then Salary
if (x.Name != y.Name) return x.Name.CompareTo(y.Name);
if (x.Age != y.Age) return x.Age.CompareTo(y.Age);
return x.Salary.CompareTo(y.Salary);
}
}
class Program
{
static Random _random = new Random();
static List<Record> _list;
static void Main(string[] args)
{
Profile("SortUsingLinqMethodChain", 50, InitList, SortUsingLinqMethodChain);
Profile("SortUsingLinqComparer", 50, InitList, SortUsingLinqComparer);
Profile("SortUsingListSort", 50, InitList, SortUsingListSort);
}
static void InitList()
{
_list = new List<Record>();
for (int i = 0; i < 10000; i++)
{
_list.Add(new Record { Name = RandomString(12), Age = RandomAge() });
}
}
static void SortUsingLinqMethodChain()
{
// NOTE: the `ToList` materialization may not be necessary at all
// This totally depends on what you want to do with the result.
_list = _list.OrderBy(item => item.Name)
.ThenBy(item => item.Age)
.ThenBy(item => item.Salary).ToList();
}
static void SortUsingLinqComparer()
{
// NOTE: the `ToList` materialization may not be necessary at all
// This totally depends on what you want to do with the result.
_list = _list.OrderBy(item => item, new RecordComparer()).ToList();
}
static void SortUsingListSort()
{
_list.Sort(new RecordComparer());
}
// based on http://stackoverflow.com/a/1344242/40347
public static string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[_random.Next(s.Length)]).ToArray());
}
public static int RandomAge()
{
return _random.Next(100) + 1;
}
public static double RandomSalary()
{
return _random.NextDouble() * 100000;
}
// based on http://stackoverflow.com/a/1048708/40347
static double Profile(string description, int iterations, Action init, Action func)
{
// Run at highest priority to minimize fluctuations
// caused by other processes/threads
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
// warm up
init();
func();
var watch = new Stopwatch();
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
for (int i = 0; i < iterations; i++)
{
init();
watch.Start();
func();
watch.Stop();
}
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
return watch.Elapsed.TotalMilliseconds;
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用系统线程;
课堂记录
{
公共字符串名称{get;set;}
公共整数{get;set;}
公共双薪{get;set;}
}
类记录器比较器:IComparer
{
公共整数比较(记录x,记录y)
{
//按姓名、年龄和薪水排序
如果(x.Name!=y.Name)返回x.Name.CompareTo(y.Name);
如果(x.Age!=y.Age)返回x.Age.CompareTo(y.Age);
返回x.Salary.CompareTo(y.Salary);
}
}
班级计划
{
静态随机_Random=新随机();
静态列表_列表;
静态void Main(字符串[]参数)
{
配置文件(“SortUsingLinqMethodChain”,50,初始列表,SortUsingLinqMethodChain);
简介(“SortUsingLinqComparer”,50,初始列表,SortUsingLinqComparer);
配置文件(“SortUsingListSort”,50,InitList,SortUsingListSort);
}
静态void InitList()
{
_列表=新列表();
对于(int i=0;i<10000;i++)
{
_添加(新记录{Name=RandomString(12),Age=RandomAge()});
}
}
静态void SortUsingLinqMethodChain()
{
//注:“ToList”的具体化可能根本没有必要
//这完全取决于你想对结果做什么。
_list=\u list.OrderBy(item=>item.Name)
.ThenBy(item=>item.Age)
.ThenBy(item=>item.Salary).ToList();
}
静态void SortUsingLinqComparer()
{
//注:“ToList”的具体化可能根本没有必要
//这完全取决于你想对结果做什么。
_list=_list.OrderBy(item=>item,newrecordcomparer()).ToList();
}
静态void SortUsingListSort()
{
_排序(新的RecordComparer());
}
//基于http://stackoverflow.com/a/1344242/40347
公共静态字符串RandomString(int-length)
{
常量字符串chars=“abcdefghijklmnopqrstuvwxyz012456789”;
返回新字符串(可枚举。重复(字符,长度)
.选择(s=>s[_random.Next(s.Length)]).ToArray();
}
公共静态int随机化()
{
返回_random.Next(100)+1;
}
公共静态双随机薪酬()
{
返回_random.NextDouble()*100000;
}
//基于http://stackoverflow.com/a/1048708/40347
静态双配置文件(字符串描述、int迭代、Action init、Action func)
{
//以最高优先级运行以最小化波动
//由其他进程/线程引起
Process.GetCurrentProcess().PriorityClass=ProcessPriorityClass.High;
Thread.CurrentThread.Priority=ThreadPriority.Highest;
//热身
init();
func();
var watch=新秒表();
//清理
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
对于(int i=0;i
您对如何对列表进行排序做了哪些研究?你发现了什么?您在实施研究中发现的解决方案时遇到了哪些问题?我考虑了sortset,但我认为这还不够满足我的需求性能数据的存储方式?它只是内存中的一个列表吗?你是怎么弄到的?@Trườ你写的具体实现是什么?你在性能测试中发现了什么?比你的要求低了多少?@enkryptor是的,我的名单在记忆中。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
class Record
{
public string Name { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
}
class RecordComparer : IComparer<Record>
{
public int Compare(Record x, Record y)
{
// Sort by Name, Age, and then Salary
if (x.Name != y.Name) return x.Name.CompareTo(y.Name);
if (x.Age != y.Age) return x.Age.CompareTo(y.Age);
return x.Salary.CompareTo(y.Salary);
}
}
class Program
{
static Random _random = new Random();
static List<Record> _list;
static void Main(string[] args)
{
Profile("SortUsingLinqMethodChain", 50, InitList, SortUsingLinqMethodChain);
Profile("SortUsingLinqComparer", 50, InitList, SortUsingLinqComparer);
Profile("SortUsingListSort", 50, InitList, SortUsingListSort);
}
static void InitList()
{
_list = new List<Record>();
for (int i = 0; i < 10000; i++)
{
_list.Add(new Record { Name = RandomString(12), Age = RandomAge() });
}
}
static void SortUsingLinqMethodChain()
{
// NOTE: the `ToList` materialization may not be necessary at all
// This totally depends on what you want to do with the result.
_list = _list.OrderBy(item => item.Name)
.ThenBy(item => item.Age)
.ThenBy(item => item.Salary).ToList();
}
static void SortUsingLinqComparer()
{
// NOTE: the `ToList` materialization may not be necessary at all
// This totally depends on what you want to do with the result.
_list = _list.OrderBy(item => item, new RecordComparer()).ToList();
}
static void SortUsingListSort()
{
_list.Sort(new RecordComparer());
}
// based on http://stackoverflow.com/a/1344242/40347
public static string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[_random.Next(s.Length)]).ToArray());
}
public static int RandomAge()
{
return _random.Next(100) + 1;
}
public static double RandomSalary()
{
return _random.NextDouble() * 100000;
}
// based on http://stackoverflow.com/a/1048708/40347
static double Profile(string description, int iterations, Action init, Action func)
{
// Run at highest priority to minimize fluctuations
// caused by other processes/threads
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
// warm up
init();
func();
var watch = new Stopwatch();
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
for (int i = 0; i < iterations; i++)
{
init();
watch.Start();
func();
watch.Stop();
}
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
return watch.Elapsed.TotalMilliseconds;
}
}