#9 Access a list in list in list
Books.Authors.Awards, a List in a List in a List
Initial Code
The following code runs at the beginning and creates some variables/services used in the following samples.
@{
var persons = AsList(App.Data["Persons"]);
var books = AsList(App.Data["Books"]);
}
Show only books of Awarded Authors #1
This example first gets book, checks the authors and checks if they have awards with LINQ Any()
.
Output
- Hitchhikers Guide to the Galaxy
with Hugo Award (1 awards)
- Phishing for Phools
with Nobel Peace Prize (1 awards)
@{
// this keeps all books whose authors have awards
var booksWithAwardedAuthors = books
.Where(b => AsList(b.Authors as object).Any(a => a.Awards.Count > 0));
}
<ol>
@foreach (var book in booksWithAwardedAuthors) {
var awards = AsList(book.Authors as object).SelectMany(a => AsList(a.Awards as object));
<li><strong>@book.Title</strong>
with @string.Join(",", awards.Select(a => a.Name)) (@awards.Count() awards)
</li>
}
</ol>
Now the list of books NOT in that list
And now the opposite list, so all books which don't contain one of the books with authors. It gets the "other" books by filtering the list to exclude the ones it found first. That demonstrates how to use Contains(x as object)
. The Contains(...)
cannot work with dynamic
, so we must tell it it's an object for it to work.
Output
- Good Omens
- The Last Continent
@{
var otherBooks = books.Where(b => !booksWithAwardedAuthors.Contains(b as object));
}
<ol>
@foreach (var book in otherBooks) {
<li><strong>@book.Title</strong></li>
}
</ol>
Now the same using GroupBy
Now let's do the same, but using GroupBy
to group by awarded authors and not-awarded authors:
Output
-
Authors with Awards: True
-
Hitchhikers Guide to the Galaxy
-
Phishing for Phools
-
Authors with Awards: False
-
Good Omens
-
The Last Continent
@{
var booksGroupedByAuthorAwards = books
.GroupBy(b => (AsList(b.Authors as object).Any(a => a.Awards.Count > 0)));
}
<ul>
@foreach (var group in booksGroupedByAuthorAwards) {
<li>
Authors with Awards: @group.Key
<ul>
@foreach (var book in group) {
<li>
@book.Title
</li>
}
</ul>
</li>
}
</ul>
#9 Access a list in list in list
@inherits Custom.Hybrid.Razor14
@using ToSic.Razor.Blade;
@using System.Linq;
<!-- unimportant stuff, hidden -->
<div @Sys.PageParts.InfoWrapper()>
@Html.Partial("../shared/DefaultInfoSection.cshtml")
<div @Sys.PageParts.InfoIntro()>
<h2>Books.Authors.Awards, a List in a List in a List</h2>
</div>
</div>
@{
var persons = AsList(App.Data["Persons"]);
var books = AsList(App.Data["Books"]);
}
<h3>Show only books of Awarded Authors #1</h3>
<p>This example first gets book, checks the authors and checks if they have awards with LINQ <code>Any()</code>. </p>
@{
// this keeps all books whose authors have awards
var booksWithAwardedAuthors = books
.Where(b => AsList(b.Authors as object).Any(a => a.Awards.Count > 0));
}
<ol>
@foreach (var book in booksWithAwardedAuthors) {
var awards = AsList(book.Authors as object).SelectMany(a => AsList(a.Awards as object));
<li><strong>@book.Title</strong>
with @string.Join(",", awards.Select(a => a.Name)) (@awards.Count() awards)
</li>
}
</ol>
<h3>Now the list of books NOT in that list</h3>
<p>And now the opposite list, so all books which don't contain one of the books with authors. It gets the "other" books by filtering the list to exclude the ones it found first. That demonstrates how to use <code>Contains(x as object)</code>. The <code>Contains(...)</code> cannot work with <code>dynamic</code>, so we must tell it it's an object for it to work.</p>
@{
var otherBooks = books.Where(b => !booksWithAwardedAuthors.Contains(b as object));
}
<ol>
@foreach (var book in otherBooks) {
<li><strong>@book.Title</strong></li>
}
</ol>
<h3>Now the same using GroupBy</h3>
<p>Now let's do the same, but using <code>GroupBy</code> to group by awarded authors and not-awarded authors:</p>
@{
var booksGroupedByAuthorAwards = books
.GroupBy(b => (AsList(b.Authors as object).Any(a => a.Awards.Count > 0)));
}
<ul>
@foreach (var group in booksGroupedByAuthorAwards) {
<li>
Authors with Awards: @group.Key
<ul>
@foreach (var book in group) {
<li>
@book.Title
</li>
}
</ul>
</li>
}
</ul>
@* Footer *@
@Html.Partial("../Shared/Layout/FooterWithSource.cshtml", new { Sys = Sys })