简体   繁体   中英

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. 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.

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 . 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);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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