使用LINQ按范围分组

12

我们如何使用分组范围来表示等于或大于?

var data = new[] {
    new { Id = 0, Price = 2 },
    new { Id = 1, Price = 10 },
    new { Id = 2, Price = 30 },
    new { Id = 3, Price = 50 },
    new { Id = 4, Price = 120 },
    new { Id = 5, Price = 200 },
    new { Id = 6, Price = 1024 },
};

var ranges = new[] { 10, 50, 100, 500 };
var grouped = data.GroupBy( x => ranges.FirstOrDefault( r => r > x.Price ) );

grouped ouput is 
price 10-50 -> 3 
price 50-100 -> 1 
price 100-500 -> 2 

所需输出按照使用的范围相等或大于该范围分组

price >= 10 -> 6
price >= 50 -> 4
price >= 100 -> 3
price >= 500 -> 1

“100 -> 2” 应该改为 “100 -> 3”,因为您似乎使用了价格等于或大于所使用范围的商品数量。 (顺便说一句,您应该尝试澄清您的问题,因为您没有提到任何计数方式) - Francis P
@Francis P 谢谢..我编辑了我的帖子..我需要的是价格等于或大于所使用范围的物品数量。 - stackCoder
2个回答

13
var grouped = ranges.Select(r => new { 
            Price = r, 
            Count = data.Where(x => x.Price >= r).Count() });

另一个选项是(如果您有大量数据,则分组比为每个价格组枚举所有数据更好):

var priceGroups = data.GroupBy(x => ranges.FirstOrDefault(r => r > x.Price))
                      .Select(g => new { Price = g.Key, Count = g.Count() })
                      .ToList();

var grouped = ranges.Select(r => new
{
    Price = r,
    Count = priceGroups.Where(g => g.Price > r || g.Price == 0).Sum(g => g.Count)
});

@cosmicgate,我在你的问题中没有看到任何类别。那是什么? - Sergey Berezovskiy
@cosmicgate 抱歉,但是新的需求使当前的答案无效。我认为最好为此创建一个新问题。 - Sergey Berezovskiy
@cosmicgate,我可以给你一个提示,让你知道从哪里开始——我认为你需要使用复合键来对数据进行分组data.GroupBy(x => new { x.cat, price = ranges.FirstOrDefault(r => r > x.Price) })。再次抱歉——现在没有空闲时间更深入地研究您的要求。如果您遇到困难,请在SO上提出新问题——有人会帮助您 :) - Sergey Berezovskiy

1

分组将分区源分组,每个项目分配到一个组中。

你所拥有的是一个不错的开端:

var data = new[] {
    new { Id = 0, Price = 2 },
    new { Id = 1, Price = 10 },
    new { Id = 2, Price = 30 },
    new { Id = 3, Price = 50 },
    new { Id = 4, Price = 120 },
    new { Id = 5, Price = 200 },
    new { Id = 6, Price = 1024 },
};

var ranges = new[] { 10, 50, 100, 500 };
var grouped = data.GroupBy( x => ranges.FirstOrDefault( r => r <= x.Price ) );

接着做:

int soFar = 0;
Dictionary<int, int> counts = grouped.ToDictionary(g => g.Key, g => g.Count());
foreach(int key in counts.Keys.OrderByDescending(i => i))
{
  soFar += counts[key];
  counts[key] = soFar;
}

或者如果你想用一条linq语句完成它:

int soFar = 0;
var grouped = data
  .GroupBy( x => ranges.FirstOrDefault( r => r <= x.Price ) )
  .OrderByDescending(g => g.Key)
  .Select(g =>
  {
    soFar += g.Count();
    return new Tuple<int, int>(g.Key, soFar)
  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接