Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 列表的多列并行排序<;T>;_C#_Linq_Sorting_Parallel Processing_Task Parallel Library - Fatal编程技术网

C# 列表的多列并行排序<;T>;

C# 列表的多列并行排序<;T>;,c#,linq,sorting,parallel-processing,task-parallel-library,C#,Linq,Sorting,Parallel Processing,Task Parallel Library,对于列表,我需要实现多列排序,其中列名和排序方向在运行时是已知的。我使用了System.Linq.Dynamic OrderByAPI,它可以将列名和排序方向作为串联字符串,因此以下代码可以工作: List<T> data = DataCollection; // Stored in Cache var sortedData = data.OrderBy("Col1 asc, Col2 desc, Col3 asc,Col4 asc"); 问题: 有没有更好的方法实现同样的目标

对于
列表
,我需要实现多列排序,其中列名和排序方向在运行时是已知的。我使用了
System.Linq.Dynamic OrderBy
API,它可以将列名和排序方向作为串联字符串,因此以下代码可以工作:

List<T> data = DataCollection; // Stored in Cache
var sortedData = data.OrderBy("Col1 asc, Col2 desc, Col3 asc,Col4 asc");
问题:

  • 有没有更好的方法实现同样的目标
  • 对于integer来说,它很简单,如何翻译我的
    多列排序的版本,因为选择分区将是一件复杂的事情

任何可以将我设置在正确路径上的指针

最合乎逻辑的选择是从LINQ切换到

不幸的是,虽然
System.Linq.Dynamic
OrderBy
方法可以工作,但它实际上会命中
可枚举
方法重载,因此对需要绑定到相应的
可并行枚举
重载的
并行查询
没有影响。另外,动态LINQ
OrderBy
实现使用内部类,因此不可能在外部扩展它(没有源代码)

仍然存在一个解决方案。您可以使用以下自定义扩展方法。它所做的是使用动态LINQ构建一个伪查询,然后使用相对简单的方法将与订单相关的
Queryable
调用替换为相应的
parallelenumable
方法:


然后比较性能。

你试过PLINQ吗?我很想把它转移到一个有描述的数据库来管理索引和后续排序。@Ivan你是说AsParallel,这对linq动态多列排序有效吗,我没有试过如果你使用linq to sql,linq所做的就是将查询转发到sql Server。这就是所有处理将发生的地方,您的代码无法控制服务器如何进行排序。另一种方法是将所有数据放入一个
列表
,并使用某种并行排序——如果有PLINQ,则内置PLINQ,或者类似于您发布的内容。这是否比让服务器来做要快,这是一个悬而未决的问题。类似于
mylist.AsParallel().OrderBy(s=>s.Col1)。然后by(s=>s.Col2)。然后by(s=>s.Col3)。然后by(s=>s.Col4)
work?非常好用,谢谢@Ivan,尽管我已经意识到在这个过程中,PLINQ做得同样好,非常感谢@Mrinal欢迎你,很高兴能帮助collegue(看到你在提问时感到有点奇怪:):),我确实充分利用了so的能力,提出了各种各样的问题,我不完全理解。在这个过程中,我得到了这么多好的解决方案,如果我用心去做,这可能是不可能的。充分利用社区的潜力。谢谢,如果计划发生变化,一定要主动伸出援助之手:)。
public class CustomSort
{   
    // Fetch Partition
    public static int Partition(List<int> list, int left, int right)
    {
        int start = left;
        int pivot = list[start];
        left++;
        right--;

        while (true)
        {
            while (left <= right && list[left] <= pivot)
                left++;

            while (left <= right && list[right] > pivot)
                right--;

            if (left > right)
            {
                list[start] = list[left - 1];
                list[left - 1] = pivot;

                return left;
            }


            int temp = list[left];
            list[left] = list[right];
            list[right] = temp;

        }
    }

    // Quick Sort serial
    public static void QuickSort(List<int> list, int left, int right)
    {
        if (list == null || list.Count <= 1)
            return;

        if (left < right)
        {
            int pivotIdx = Partition(list, left, right);
            QuickSort(list, left, pivotIdx - 1);
            QuickSort(list, pivotIdx, right);
        }
    }

    // Quick Sort Parallel
    public static void QuickSortParallel(List<int> list, int left, int right)
    {
        if (list == null || list.Count <= 1)
            return;

        if (left < right)
        {
            int pivotIdx = Partition(list, left, right);        

            Task leftTask = Task.Run(() => QuickSort(list, left, pivotIdx - 1));
            Task rightTask = Task.Run(() => QuickSort(list, pivotIdx, right));

            Task.WaitAll(new[] { leftTask, rightTask });

        }
    }
}
public static class DynamicPLINQ
{
    public static OrderedParallelQuery<T> OrderBy<T>(this ParallelQuery<T> source, string ordering, params object[] values)
    {
        var query = Enumerable.Empty<T>().AsQueryable();
        var orderedQuery = query.OrderBy(ordering, values);
        var binder = new ParallelQueryBinder();
        binder.source = query;
        binder.target = source;
        var queryExpr = binder.Visit(orderedQuery.Expression);
        return (OrderedParallelQuery<T>)query.Provider.Execute(queryExpr);
    }

    class ParallelQueryBinder : ExpressionVisitor
    {
        public object source;
        public object target;
        protected override Expression VisitConstant(ConstantExpression node)
        {
            if (node.Value == source)
                return Expression.Constant(target);
            return base.VisitConstant(node);
        }
        protected override Expression VisitUnary(UnaryExpression node)
        {
            if (node.NodeType == ExpressionType.Quote)
                return Visit(node.Operand);
            return base.VisitUnary(node);
        }
        static readonly string[] Methods = { "OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending" };
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.IsStatic && node.Method.DeclaringType == typeof(Queryable) && Methods.Contains(node.Method.Name))
            {
                var arguments = node.Arguments.Select(Visit).ToArray();
                var result = Expression.Call(typeof(ParallelEnumerable), node.Method.Name, node.Method.GetGenericArguments(), arguments);
                return result;
            }
            return base.VisitMethodCall(node);
        }
    }
}
var sortedData = data.AsParallel()
    .OrderBy("Col1 asc, Col2 desc, Col3 asc,Col4 asc")
    .ToList();