gpt4 book ai didi

C# - 将多对多对象列表转换为两个对象列表的不同组合列表

转载 作者:行者123 更新时间:2023-12-02 12:52:25 25 4
gpt4 key购买 nike

我似乎无法掌握如何做到这一点,也找不到简单的方法来解释它......所以我希望这个简化的示例有意义。

被给予一个对象列表<>,如下:

public class FlatManyToMany
{
public string BookTitle { get; set; }
public int BookPages { get; set; }
public string ReaderName { get; set; }
public int ReaderAge { get; set; }
}

var flatManyToMany = new List<FlatManyToMany>();

flatManyToMany.Add(new FlatManyToMany { BookTitle = "How to Do This Double List", BookPages = 105, ReaderName = "Kyle", ReaderAge = 29 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "How to Do This Double List", BookPages = 105, ReaderName = "Bob", ReaderAge = 34 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Gone With Jon Skeet", BookPages = 192, ReaderName = "Kyle", ReaderAge = 29 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Gone With Jon Skeet", BookPages = 192, ReaderName = "James", ReaderAge = 45 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Gone With Jon Skeet", BookPages = 192, ReaderName = "Brian", ReaderAge = 15 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Why Is This So Hard?", BookPages = 56, ReaderName = "Kyle", ReaderAge = 29 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Why Is This So Hard?", BookPages = 56, ReaderName = "James", ReaderAge = 45 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Why Is This So Hard?", BookPages = 56, ReaderName = "Brian", ReaderAge = 15 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Impostor Syndrome", BookPages = 454, ReaderName = "Kyle", ReaderAge = 29 });
flatManyToMany.Add(new FlatManyToMany { BookTitle = "Self Doubt and You", BookPages = 999, ReaderName = "Kyle", ReaderAge = 29 });

我需要的结果是两个对象列表的列表,如下所示:

public class ResultDoubleList
{
public List<Book> Books { get; set; } = new List<Book>();
public List<Reader> Readers { get; set; } = new List<Reader>();
}

public class Book
{
public string Title { get; set; }
public int Pages { get; set; }
}

public class Reader
{
public string Name { get; set; }
public int Age { get; set; }
}

这本书在最终结果中应该只出现一次,但读者可以出现多次。如果同一读者阅读过多本书,则可以将它们放在一起。

这就是我需要结果的方式:

List<ResultDoubleList> results = new List<ResultDoubleList>();

result(1):
Books
How to Do This Double List 105
Readers
Kyle 29
Bob 34

result(2):
Books
Gone With Jon Skeet 192
Why Is This So Hard? 56
Readers
Kyle 29
James 45
Brian 15

result(3):
Books
Impostor Syndrome 454
Self Doubt and You 999
Readers
Kyle 29

最终结果是图书列表和读者列表的不同组合。这本书只出现一次,但读者可以出现多次。具有完全相同读者列表的书籍将被分组在一起。

即使有人能告诉我这种最终结果叫什么,我也会很感激。

最佳答案

您可以使用这个冗长的 LINQ 查询来完成此操作:

var result = flatManyToMany
.GroupBy(f1 => (f1.BookTitle, f1.BookPages))
.Select(g1 => (bookInfo: g1.Key,
readers:
g1.Select(f2 => new Reader { Name= f2.ReaderName, Age= f2.ReaderAge }),
readerKey:
String.Join("|", g1.Select(f3 => $"{f3.ReaderName}{f3.ReaderAge}"))))
.GroupBy(a1 => a1.readerKey)
.Select(g2 => new ResultDoubleList {
Books = g2.Select(a2 => new Book {
Title = a2.bookInfo.BookTitle,
Pages = a2.bookInfo.BookPages
}
).ToList(),
Readers = g2.First().readers.ToList() // Any will do, since they have the same readers
})
.ToList();

这个想法是分组两次。每本书一次,每个读者组一次。

首先,我们按 ValueTuple 进行分组(f1.BookTitle, f1.BookPages) 。与创建 Book 相比的优势对象是ValueTuple自动覆盖EqualsGetHashCode 。对于用作字典或查找中的键的类型,这是必需的,如 GroupBy做。或者,您可以覆盖 Book 中的这些方法。类(class)和分组 Book对象。如果您有唯一的图书 ID,请使用此 ID。

然后我们用 Select 创建一个临时结果。我们再次创建一个包含 3 个字段的元组。包含书籍信息的元组,可枚举 Reader对象,最后,我们创建一个包含所有读者的字符串作为键,稍后我们将使用该字符串按唯一的读者组进行分组。如果您有唯一的读者 ID,请使用此 ID,而不是姓名和年龄。

到目前为止,我们已经有了

IEnumerable<(
(string BookTitle, int BookPages) bookInfo,
IEnumerable<Reader> readers,
string readerKey
)>

现在我们按readerKey分组然后创建 ResultDoubleList 的列表对象。

如果您难以理解详细信息,请将 LINQ 查询分解为多个查询。通过使用“Make Explicit”重构,您可以看到得到的结果类型。 (这就是我从上面得到复杂的 IEnumerable<T> 的方式。)这还允许您检查调试器中的中间结果。


本次测试...

int resultNo = 1;
foreach (ResultDoubleList item in result) {
Console.WriteLine($"\r\nresult({resultNo++}):");
Console.WriteLine("Books");
foreach (var book in item.Books) {
Console.WriteLine($" {book.Title,-28} {book.Pages,3}");
}
Console.WriteLine("Readers");
foreach (var reader in item.Readers) {
Console.WriteLine($" {reader.Name,-8} {reader.Age,2}");
}
}
Console.ReadKey();

...产量:

result(1):
Books
How to Do This Double List 105
Readers
Kyle 29
Bob 34

result(2):
Books
Gone With Jon Skeet 192
Why Is This So Hard? 56
Readers
Kyle 29
James 45
Brian 15

result(3):
Books
Impostor Syndrome 454
Self Doubt and You 999
Readers
Kyle 29

关于C# - 将多对多对象列表转换为两个对象列表的不同组合列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58758725/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com