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

时间:2015-10-15 15:46:07

标签: c# .net linq

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

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

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

和另一个列表,它定义了应分割哪些地方myList

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

获取嵌套列表的最短方法是将myList拆分为borders中定义的值,例如:

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

我已经通过手动循环遍历列表来解决它,但我可以想象使用Linq更容易和更短。

编辑:有一个简化:数字不能与边框相同,因此myListborders中的数字不可能同时包含在内。

1 个答案:

答案 0 :(得分:14)

由于您希望将数字分组到不同的组中,因此您需要使用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的数字与当前或下一个border元素匹配会更有效。因此,此解决方案为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);
}