根据边框值将列表拆分为子列表

本文关键字:列表 拆分 边框 | 更新日期: 2023-09-27 18:17:49

我想根据另一个列表的条目将现有排序列表拆分为多个子列表。

假设我有一个这样的数组:

List<int> myList = [1,3,7,23,56,58,164,185];

和另一个列表,它定义了myList应该在哪里被分割:

List<int> borders = [4,59,170];

获得myListborders中定义的值处分割的嵌套列表的最短方法是什么,即:

[[1,3],[7,23,56,58],[164],[185]]

我已经通过手动遍历列表解决了这个问题,但我可以想象使用Linq会更容易、更短。

编辑:有一个简化:数字不能和边框一样,所以一个数字不可能同时包含在myListborders

根据边框值将列表拆分为子列表

由于您希望将数字分组到不同的组中,因此您将希望使用GroupBy。困难只是你把它当作钥匙。为此,您可以使用比数字小的最大边框值。这里假设borders通过以下方式排序:

List<int> myList = new List<int> { 1, 3, 7, 23, 56, 58, 164, 185 };
List<int> borders = new List<int> { 4, 59, 170 };
var groups = myList.GroupBy(i => borders.LastOrDefault(x => x < i));
foreach (var group in groups)
{
    Console.WriteLine("{0}: {1}", group.Key, string.Join(", ", group));
}

这会产生以下输出:

0: 1, 3
4: 7, 23, 56, 58
59: 164
170: 185

请注意,这并不是最有效的解决方案,因为它将为myList中的每个元素搜索合适的边框键。如果您的列表像示例一样排序,那么同时遍历两者并将myList的数字与当前或下一个边界元素匹配会更有效。所以这个解是O(n * m),而O(n)是可能的。从好的方面来说,这允许myList完全不排序。


对于那些对O(n)解感兴趣的人,这里有一种可能的解释,它只是对序列分组的一种非常一般的方法:

List<List<int>> groups = new List<List<int>>();
List<int> group = null;
int k = -1;
foreach (int num in myList)
{
    if (k < 0 || num > borders[k])
    {
        group = new List<int>();
        groups.Add(group);
        k++;
    }
    group.Add(num);
}