简体   繁体   English

如何在LINQ中按集对项目排序?

[英]How Do You Sort Items By Set in LINQ?

I have this simple array with the following items: 我有以下项目的简单数组:

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

I want to sort it on this way: 我想以这种方式对其进行排序:

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

As you notice, I want to sort it on descending order. 如您所见,我想按降序对其进行排序。 But on this case, there are two sets of array that was sorted on descending order: 但是在这种情况下,有两组数组以降序排列:

4, 3, 1, 0 and 1, 0 

Which produce the output: 产生输出:

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

I tried to do this using Group By: 我试图使用分组依据来做到这一点:

var result = arrayInput.GroupBy(c => c).Select(a => a.OrderBy(d => d).First());

But this produces only 4, 3, 1, 0 and I need to append the not selected integers as sorted so that it will be: 但是,这仅产生4, 3, 1, 0 ,我需要追加未选择整数作为排序所以,这将是:

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

Here's how I'd do that. 这就是我要做的。 Basically you want to try putting each number into a group of sets. 基本上,您想尝试将每个数字放入一组集合中。 The first one that doesn't already have that number is the one it actually goes in and if none have it then you add a new set. 第一个没有该编号的是它实际输入的编号,如果没有编号,则添加一个新编号。 In this way the first set will have all unique numbers, the second with have all numbers that are duplicated as least once, and so on. 这样,第一个集合将具有所有唯一编号,第二个集合将具有所有重复至少一次的编号,依此类推。 Then at the end you return items for each of the sets ordering each set as you go. 然后,最后返回每个集合的项目,并按顺序排序每个集合。

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

As usually Aggregate extension method can do everything 通常, 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 };

Approach with immutable collections 处理不可变的集合

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

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

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