I had to model a system (a library) using jagged arrays.
Each Physical Book must be on a shelf.
A Bookshelf is an array of shelves.
A Catalog is an array of bookshelves.
Therefore, a Catalog "is an array of arrays of arrays" of Physical Books.
I had to do everything using three classes: "PhysicalBook", "Bookshelf" and "Catalog".
public class PhysicalBook{
public string ID {get; private set;}
//...
}
public class Bookshelf{
public PhysicalBook[][] bookshelf;
//...
}
public class Catalog{
public Bookshelf[] listBookshelves;
//...
}
My question is: how can I iterate through each "PhysicalBook" of the jagged array "listBookshelves"?
I want to write a method named "SearchPhysicalBook" inside the class "Catalog" that, given a string "ID", find wheter the associated book is present or not in an instance of "Catalog".
public bool SearchPhysicalBook(string id)
{
for (int i=0; i<this.listBookshelves.Length; i ) {
for (int j = 0; j < this.listBookshelves.Length; j )
{
for (int k = 0; k < this.listBookshelves.Length; k ) {
/*if (listBookshelves[i][j][k].ID==id)
return true;*/
}
}
}
return false;
}
}
What I commented in this last lines of code is wrong.
Can anyone help me, please?
CodePudding user response:
You can use foreach
instead of for
, it is more readable, like so:
public PhysicalBook SearchPhysicalBookById(string id, Catalog catalog)
{
foreach (Bookshelf bookshelf in catalog.listBookshelves)
{
foreach (PhysicalBook[] physicalBooksInShelf in bookshelf.bookshelf)
{
PhysicalBook book = physicalBooksInShelf.FirstOrDefault(book => book.ID.Equals(id));
if (book != null)
{
return book;
}
}
}
return null;
}
CodePudding user response:
Often we query such collections with a help of Linq, in your case you can use SelectMany
to flatten jagged array:
using System.Linq;
...
public bool SearchPhysicalBook(string id) => listBookshelves
.SelectMany(shelf => shelf
.bookshelf
.SelectMany(line => line))
.Any(book => book.ID == id);
In order not to repeat the compicated fragment, you can extract a method:
private IEnumerable<PhysicalBook> AllBooks => listBookshelves
.SelectMany(shelf => shelf
.bookshelf
.SelectMany(line => line));
And then you can have SearchPhysicalBook
as easy as
// If book exists
public bool SearchPhysicalBook(string id) =>
AllBooks.Any(book => book.ID == id);
// Book if it exists, null if there's no such a book:
public PhysicalBook BookByID(string id) =>
AllBooks.FirstOrDefault(book => book.ID == id);