简体   繁体   English

将列表按升序和降序排序

[英]Sorting a list in ascending and descending order

I have a collection of integers eg 我有一个整数的集合,例如

INPUT EXAMPLE 输入示例

4,7,9,8,20,56,78,34,2,76,84,98

I need to sort this list in a way that any number til 20 will be sorted in ascending order and above 20 will be sorted in descending order. 我需要对列表进行排序,直到任何数字til 20都将以升序排序,而大于20的数字将以降序排序。 So output will be : 因此输出将是:

OUTPUT EXAMPLE 输出示例

2,4,7,8,9,20,98,84,78,76,56,34

I wrote a comparer for it. 我为此写了一个比较器。 but now trying for more clean approach may be by using the existing tools like orderby. 但是现在尝试使用更干净的方法可能是使用现有的工具,例如orderby。

You can do that using two sort groups: 您可以使用两个排序组来做到这一点:

list.OrderBy(i => i <= 20 ? i : int.MaxValue) // sort numbers less than 20 ascending; put numbers greater than 20 at the end
    .ThenByDescending(i => i)  // sort remaining numbers descending

You can trivially do this using a custom comparer: 您可以使用自定义比较器轻松地做到这一点:

public class MyCustomComparer : IComparer<int>
{
    private readonly int _cutOffPointInclusive;

    public MyCustomComparer(int cutOffPointInclusive)
    {
        _cutOffPointInclusive = cutOffPointInclusive;
    }

    public int Compare(int x, int y)
    {
        if (x <= _cutOffPointInclusive || y <= _cutOffPointInclusive)
        {
            return x.CompareTo(y);
        }
        else 
        {               
            return y.CompareTo(x);
        }
    }
}

This sorts ascendingly when either value to compare is lower than or equal to the cutoff point (both to push the greater values to the top and to sort the values up till the cutoff point ascendingly), and descendingly when both are greater than the cutoff point (to actually sort those greater values descendingly). 当要比较的任何一个值小于或等于截止点时,这将升序排序(将较大的值推到顶部并将值依次升至截止点),而当两个值均大于截止点时,则降序排序(实际上是按降序排序那些较大的值)。

Tested using: 测试使用:

var testData = new List<int>{ 4,7,9,8,20,56,78,34,2,76,84,98 };

testData.Sort(new MyCustomComparer(20));

foreach (var i in testData)
{
    Console.WriteLine(i);
}

Output: 输出:

2
4
7
8
9
20
98
84
78
76
56
34

See also http://ideone.com/YlVH8i . 另请参见http://ideone.com/YlVH8i So I don't really think this isn't "clean", but just fine. 因此,我并不是真的认为这不是“干净”的,但是还不错。

Why don't use two steps? 为什么不使用两个步骤?

var bellow = originallist.Where(i => i <= 20).OrderBy(i);
var above= originallist.Where(i => i > 20).OrderByDescending(i);

var sorted = bellow.Concat(above).ToList();
int[] a = { 4, 7, 9, 8, 20, 56, 78, 34, 2, 76, 84, 98 };

var b = a.OrderBy(i => i > 20 ? int.MaxValue - i : i);

If possible, I recommend sorting in-place. 如果可能,我建议就地排序。 For example ( can be improved ) 例如(可以改进)

Array.Sort(a, (i1, i2) => (i1 > 20 ? int.MaxValue - i1 : i1) - (i2 > 20 ? int.MaxValue - i2 : i2));
[Test]
        public void SortTill20AscRestDesc()
        {
            var src = new[] {4, 7, 9, 8, 20, 56, 78, 34, 2, 76, 84, 98};
            var expected = new[] {2, 4, 7, 8, 9, 20, 98, 84, 78, 76, 56, 34};
            var result = src
                .Select(
                    i => new
                    {
                        IsAbove20 = i > 20,
                        Value = i
                    }
                )
                .OrderBy(e => e.IsAbove20)
                .ThenBy(e => e.IsAbove20 ? int.MaxValue : e.Value)
                .ThenByDescending(e => e.Value)
                .Select(e=>e.Value);

            Assert.That(result.SequenceEqual(expected), Is.True);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM