Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.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/sorting/2.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# LINQ选择性排序,偏序_C#_Sorting_Union_Partial - Fatal编程技术网

C# LINQ选择性排序,偏序

C# LINQ选择性排序,偏序,c#,sorting,union,partial,C#,Sorting,Union,Partial,假设我有一个对象列表: var items = new { new { Order = 0 }, new { Order = 1 }, new { Order = -1 }, new { Order = 3 }, new { Order = 2 }, new { Order = -1 } }; 我需要对其进行排序,以便具有顺序>-1的项目按顺序升序排列在列表的顶部,并且具有顺序==-1的剩余项目紧随其后 有没有比使用Conact()和Where(

假设我有一个对象列表:

var items = new {
    new { Order = 0 },
    new { Order = 1 },
    new { Order = -1 },
    new { Order = 3 },
    new { Order = 2 },
    new { Order = -1 }
};
我需要对其进行排序,以便具有
顺序>-1
的项目按顺序升序排列在列表的顶部,并且具有
顺序==-1
的剩余项目紧随其后

有没有比使用
Conact()
Where()
子句更优雅的方法:

var orderedItems = items.Where(x => x.Order > -1).OrderBy(x => x.Order)
                   .Conact(items.Where(x => x.Order == -1);
因此,在对该列表进行排序后,其如下所示:

var items = new {
    new { Order = 0 },
    new { Order = 1 },
    new { Order = 2 },
    new { Order = 3 },
    new { Order = -1 },
    new { Order = -1 }
};

另外,实际场景中的
items
列表已经是一个复杂的
IQueryable
对象。这就是为什么我试图找到进行这种选择性排序的最佳方法。

如果您按升序排序,-1应该已经在列表的顶部,因为它是最小的值

但是,更一般地说,如果您仍然希望对数据子集应用不同的排序,我不认为会有更优雅的方法,因为这正是您正在做的,并且联合在逻辑上是准确的。您试图从数据中提取两个独立的子集,对它们进行不同的排序,然后将它们合并在一起,这也是我union的用途之一。

使用a来定义所需的顺序

public class MyComparer : IComparer<int>
{
    public int Compare(int a, int b)
    {
        if ((a < 0) && (b >= 0))
        {
            return 1;
        }
        if ((a >= 0) && (b < 0))
        {
            return -1;
        }
        return int.Compare(a, b);
    }
}

正如Mike提到的,在您的示例中,它会自动工作,但假设我们希望先获取所有-1元素,然后按降序对其余元素进行排序。这可以用一个很好的技巧来完成。排序元素时可以使用多个键。第一个键可以是一个布尔值,对于所有-1值(因此它们将是第一个值),它将是
false
,对于所有其他值,它将是
true
(因此它们不会被重新排序)。第二个键可以是您想要对其余元素排序的任何键。例如:

var nums = new int[] { -1, 4, 2, 3, -1, 4, 7 };
var q = from n in nums
        orderby n != -1, n descending
        select n;
它将首先产生
n!=-1
false
,然后使用
n降序对所有元素进行排序
,因此您将得到:

-1, -1, 7, 4, 4, 3, 2
通常,当您需要处理某些元素时,尤其是在排序过程中,这一点非常有效-您只需要提供正确的排序键。

OrderBy(x=>x.Order<0?int.MaxValue:x.Order)
OrderBy(x => x.Order < 0 ? int.MaxValue : x.Order)
或者如果需要按降序排列负值

OrderBy(x => x.Order < 0 ? (long)int.MaxValue - x.Order : (long)x.Order)
OrderBy(x=>x.Order<0?(长)int.MaxValue-x.Order:(长)x.Order)

您可以试试这个-它会产生您期望的结果:

items.OrderBy(x.Order => x.Order == -1).ThenBy(x.Order => x.Order);

这里还有一个自定义比较器,如果您想先显示-1,但其他比较器是降序的,但不知何故我发现它更优雅:)注意它是为int设计的

class Comparer : IComparer<int>
{
  public int Compare(int x, int y)
  {
    if (x == -1 || y == -1) return x - y;
    return y - x;
  }
}
类比较器:IComparer
{
公共整数比较(整数x,整数y)
{
如果(x==-1 | y==-1)返回x-y;
返回y-x;
}
}

现在有点困惑……升序意味着1,2,3,不是吗?在这种排序中,-1应该自动在0之前?您应该使用
Concat
,而不是
Union
。您拼写的Concat不正确,这将返回无序的否定项。从这个问题上看,他不清楚这是否是他想要的。嗯,他并没有要求:)我将添加简单的改编。重新阅读这个问题后,根本不清楚如何处理其他负数。这个答案应该给出了大概的想法。很酷,但是你的解释让我困惑……如果!=-1个元素是先生成的,那么-1个元素不应该在末尾出现吗?或者这里到底发生了什么?这是因为布尔值的升序
true。CompareTo(false)
给出1,表示
true>false
,因此升序为
false,true
(因此
false
元素排在第一位)。不知道bool实现了IComparable。真漂亮!
class Comparer : IComparer<int>
{
  public int Compare(int x, int y)
  {
    if (x == -1 || y == -1) return x - y;
    return y - x;
  }
}