C# 操纵集合以生成压缩版本

C# 操纵集合以生成压缩版本,c#,c#-4.0,C#,C# 4.0,我目前正被一个我似乎无法理解的小功能难倒 首先,我有一个Stock类,如下所示: public class Stock { public int Id; public int LocationId; public int Quantity; } Stock日志从数据库返回,这些日志由另一项功能生成。日志表示为列表集合-但是我需要添加相同ID和LocationID组合的每个对象的数量属性,例如: 原始数据集: ID:1位置:1数量:20 ID:1位置:2数量:30 ID:

我目前正被一个我似乎无法理解的小功能难倒

首先,我有一个
Stock
类,如下所示:

public class Stock
{
    public int Id;
    public int LocationId;
    public int Quantity;
}
Stock
日志从数据库返回,这些日志由另一项功能生成。日志表示为
列表
集合-但是我需要添加相同
ID
LocationID
组合的每个对象的
数量
属性,例如:

原始数据集:

ID:1位置:1数量:20

ID:1位置:2数量:30

ID:1位置:1数量:30

ID:2位置:2数量:20

ID:1位置:2数量:30

ID:1位置:1数量:100

应返回:

压缩数据集:

ID:1位置:1数量:150

ID:1位置:2数量:60

ID:2位置:2数量:20

重申:数据集是从数据库动态返回的,不能保证会有每个
ID
LocationID
组合,我需要结果数据集在
ID
LocationID
的复合键上是唯一的

我不确定最有效的方法是什么,这阻碍了我的项目进展,任何建议或方法都将不胜感激。我认为这确实是一个知识差距,但我还没有找到任何适合我的要求(我想这是一个很奇怪的要求)

非常感谢,


Andy

您可以使用
Enumerable.GroupBy
执行分组,并使用
Enumerable.Aggregate
(在本例中,可以使用专门的
Sum
)执行聚合

大致如下:

IEnumerable<Tuple<int, int, int>> result =
    stocks.GroupBy(stock => new { id = stock.Id, locationId = stock.LocationId},
                   (key, s) => new { key.id, key.locationId, total = s.Sum(ss => ss.Quantity) });

foreach (var result in results)
{
    Console.WriteLine(result.id);
    Console.WriteLine(result.locationId);
    Console.WriteLine(result.total);
}
IEnumerable结果=
GroupBy(stock=>new{id=stock.id,locationId=stock.locationId},
(key,s)=>new{key.id,key.locationId,total=s.Sum(ss=>ss.Quantity)});
foreach(结果中的var结果)
{
Console.WriteLine(result.id);
Console.WriteLine(result.locationId);
Console.WriteLine(result.total);
}

使用
GroupBy
执行此操作:

var grouped = (from s in stocks
                group s by new { s.Id, s.LocationId }
                    into grp
                    select new Stock()
                    {
                        Id = grp.Key.Id,
                        LocationId = grp.Key.LocationId,
                        Quantity = grp.Sum(x => x.Quantity)
                    }).ToList();

最好在数据库上执行此操作,但也可以使用GroupBy实现完全相同的效果:

public class Stock
{
    public int Id;
    public int LocationId;
    public int Quantity;
}

static void Main(string[] args)
{
    var list = new List<Stock>()
        {
            new Stock(){ Id = 1, LocationId = 1, Quantity = 20},
            new Stock(){ Id = 1, LocationId = 2, Quantity = 30},
            new Stock(){ Id = 1, LocationId = 1, Quantity = 30},
            new Stock(){ Id = 2, LocationId = 2, Quantity = 20},
            new Stock(){ Id = 1, LocationId = 2, Quantity = 30},
            new Stock(){ Id = 1, LocationId = 1, Quantity = 100},

        };

    var grouped = list.GroupBy(c => new {Id = c.Id, LocationId = c.LocationId})
            .Select(g => new 
                 { 
                      Id = g.Key.Id, 
                      LocationId = g.Key.LocationId, 
                      Quantity = g.Sum(a => a.Quantity) 
                  });
    foreach(var group in grouped.OrderBy(c => c.Id))
    {
        Console.WriteLine("Id:{0} - LocationId:{1} - Quantity:{2}", group.Id, 
                 group.LocationId, group.Quantity);
    }
}
公共类股票
{
公共int Id;
公共地址ID;
公共整数;
}
静态void Main(字符串[]参数)
{
var list=新列表()
{
new Stock(){Id=1,LocationId=1,Quantity=20},
新货(){Id=1,LocationId=2,Quantity=30},
new Stock(){Id=1,LocationId=1,Quantity=30},
新货(){Id=2,LocationId=2,Quantity=20},
新货(){Id=1,LocationId=2,Quantity=30},
new Stock(){Id=1,LocationId=1,Quantity=100},
};
var grouped=list.GroupBy(c=>new{Id=c.Id,LocationId=c.LocationId})
.选择(g=>new
{ 
Id=g.Key.Id,
LocationId=g.Key.LocationId,
数量=总数量(a=>a.数量)
});
foreach(grouped.OrderBy(c=>c.Id)中的var组)
{
WriteLine(“Id:{0}-LocationId:{1}-Quantity:{2}”,group.Id,
group.LocationId、group.Quantity);
}
}

我更喜欢使用类似以下内容的SQL查询:

select id, location, sum(quantity) quant from stocktable group by id, location

这有助于在数据库本身完成计算,从而在性能方面帮助您。由于DB服务器无论如何都会读取所有数据并将其提供给应用层,因此不会对性能造成任何损失,而且您可以从简单性方面获益

你没有在数据库中执行聚合有什么原因吗?我把它作为一个C#问题发布,并且有一些有用的C#答案帮助了我,我觉得有必要将其中一个标记为答案,但是我确实实现了你提出的建议,这是一个非常有用、简单的解决方案。非常感谢。谢谢你的回答,考虑到你提到在数据库中进行聚合(我最终还是这么做了),并且仍然给出了C#答案,这正是我想要的。非常感谢。