【发布时间】:2018-07-20 06:23:15
【问题描述】:
我无法使用 LINQ 查询解决此问题。
所以我们有Book的表结构如下:
LibraryId || LibraryName || ShelveId || ShelveName || Cost || Name || ForeName || Stuff
我想先按图书馆分组,然后按书架分组。图书馆是书架的清单,书架是书的清单。性能很重要。这是真实数据的片段。
var table = new[] {
new Book (1, "Green", 42, "A", 10, "Gra", "Bar", "etc."),
new Book (1, "Green", 43, "B", 21, "Grb", "Bar", "etc."),
new Book (2, "Blue", 652, "C", 10, "Blc", "Bar", "etc."),
new Book (2, "Blue", 652, "C", 01, "Bl2", "Bar", "etc."),
new Book (2, "Blue", 123, "D", 12, "Bld", "Bar", "etc."),
new Book (8, "White", 94, "E", 14, "Foo", "Bar", "etc."),
new Book (9, "Grey", 142, "F", 11, "Foo", "Bar", "etc."),
new Book (9, "Grey", 142, "F", 12, "Bar", "Bar", "etc.")
};
类:
class Book
{
public int LibraryId {get;set;}
public string LibraryName {get;set;}
public int ShelveId {get;set;}
public string ShelveName {get;set;}
public int Cost {get;set;}
public string Name {get;set;}
public string ForeName {get;set;}
public string Stuff {get;set;}
public Book(int libraryId, string libraryName, int shelveId, string shelveName
, int cost, string name, string foreName, string stuff)
{
LibraryId = libraryId;
LibraryName = libraryName;
ShelveId = shelveId;
ShelveName = shelveName;
Cost = cost;
Name = name;
ForeName = foreName;
Stuff = stuff;
}
}
class Library
{
public int Id {get;set;}
public string Name {get;set;}
public int Cost {get;set;}
public List<Shelve> Shelves {get;set;}
public Library (Shelve shelve)
{
Id = shelve.Books[0].LibraryId;
Name = shelve.Books[0].LibraryName;
Cost = shelve.Cost;
Shelves = new List<Shelve> {shelve};
}
}
class Shelve
{
public int Id {get;set;}
public string Name {get;set;}
public int Cost {get;set;}
public List<Book> Books {get;set;}
public Shelve (Book book)
{
Id = book.ShelveId;
Name = book.ShelveName;
Cost = book.Cost;
Books = new List<Book> {book};
}
}
我用一个很好的老foreach来实现我的行为:
var libraries = new List<Library> { new Library (new Shelve(table[0])) };
foreach (var item in table.Skip(1))
{
if (item.LibraryId != libraries.Last().Id)
{
libraries.Add(new Library(new Shelve(item)));
continue;
}
if (item.ShelveId != libraries.Last().Shelves.Last().Id)
{
libraries.Last().Cost += item.Cost;
libraries.Last().Shelves.Add(new Shelve(item));
continue;
}
libraries.Last().Cost += item.Cost;
libraries.Last().Shelves.Last().Cost += item.Cost;
libraries.Last().Shelves.Last().Books.Add(item);
}
var total = libraries.Sum(x => x.Cost);
据我所知,这是一个 O(n) 的解决方案。
现在,我想重构它。我想我们可以用GroupBy 做点什么。我试过这个:
var grouped = table
.GroupBy(l => new { l.ShelveId, l.LibraryId})
.GroupBy(l => l.Key.LibraryId);
foreach(var country in grouped)
{
foreach(var state in country)
{
foreach(var personInState in state)
{
Console.WriteLine(personInState.Name);
}
}
}
但我不知道如何汇总成本并将 LibraryName 和 ShelveName 添加到每个 Library 和 Shelve。
Try it Online!(带有基本测试)
【问题讨论】:
-
能否编辑您的问题并粘贴 Library、Shelve 和 Book 的类定义?
-
@RuiJarimba 完成。
-
Library和Shelf(不是Shelve,这是一个动词)真的不应该包含Cost属性:如果我们将它们视为数据库中的表,这会破坏规范化规则。如果您愿意省略它,您可以使用嵌套查询(请参阅here)。
标签: c# performance linq refactoring