如何在LINQ中按项设置对项目进行排序?

时间:2017-08-28 16:52:13

标签: c# linq sorting

我有一个包含以下项目的简单数组:

[4, 3, 1, 1, 0, 0]

我想以这种方式对它进行排序:

[4, 3, 1, 0, 1, 0]

正如您所注意到的,我想按降序对其进行排序。但在这种情况下,有两组数组按降序排序:

4, 3, 1, 0 and 1, 0 

产生输出:

[4, 3, 1, 0, 1, 0]

我尝试使用Group By:

执行此操作
var result = arrayInput.GroupBy(c => c).Select(a => a.OrderBy(d => d).First());

但是这只生成4, 3, 1, 0,我需要将未选择的整数附加为已排序,以便它将是:

[4, 3, 1, 0, 1, 0]

2 个答案:

答案 0 :(得分:1)

这是我如何做到的。基本上你想尝试将每个数字放入一组集合中。第一个没有这个数字的是它实际进入的那个,如果没有它,那么你添加一个新的集合。通过这种方式,第一组将具有所有唯一数字,第二组具有至少一次重复的所有数字,依此类推。然后在最后,您将返回每个集合的项目,并按顺序排列每个集合。

public static IEnumerable<int> SetSort(this IEnumerable<int> nums) {
    var sets = new List<HashSet<int>>();
    foreach(var num in nums) {
        bool added = false;
        foreach(var set in sets) {
            added = set.Add(num);
            if(added) break;
        }
        if(!added){
            sets.Add(new HashSet<int> { num });
        }
    }

    foreach(var set in sets) {
        foreach(var num in set.OrderByDescending(x => x)) {
            yield return num;
        }
    }
}

答案 1 :(得分:1)

通常Aggregate扩展方法可以做任何事情

var data = new[] { 1, 2, 3, 4, 1, 0, 1, 0 };
var result = 
    data.GroupBy(i => i)
        .OrderByDescending(group => group.Key)
        .Aggregate(new { Keys = new List<int>(), Duplicates = new List<int>() }, 
                   (lists, group) =>
                   {
                       lists.Keys.Add(group.Key);
                       var duplicates = Enumerable.Repeat(group.Key, group.Count() - 1);
                       lists.Duplicates.AddRange(duplicates);
                       return lists;
                   },
                   lists => lists.Keys.Concat(lists.Duplicates));

// result is new[] { 4, 3, 2, 1, 0, 1, 1, 0 };

使用不可变集合的方法

private IEnumerable<int> SortFunc(IEnumerable<int> data)
{
    var ordered = 
        data.GroupBy(i => i)
            .OrderByDescending(group => group.Key)
            .Select(group => new
            {
                Key = group.Key,
                Duplicates = group.Skip(1)
            });

    foreach (var key in ordered.Select(group => group.Key))
    {
        yield return key;
    }

    foreach (var value in ordered.SelectMany(group => group.Duplicates))
    {
        yield return value;
    }
}