I have Book
class:
public class Book
{
public int Id {get; set;}
public string Name {get; set;}
public deciaml Price {get; set;}
}
And List of books
:
List<Book> books = new List<Book>
{
new Book
{
Id = 1,
Name = "AA",
Price = 19.0000M
},
new Book
{
Id = 2,
Name= "BB",
Price = 18.0000M
},
new Book
{
Id = 3,
Name = "CC",
Price = 30.0000M
},
new Book
{
Id = 4,
Name = "DD",
Price = 9.0000M,
},
};
Now I want to group list by price rate, like cheap, medium, expensive:
for example, cheap = 10, medium = 20, expensive = 30 grouped list would be like:
List<(decimal category, List<Book> books)
{
category: 10
books: List<Book>() {Book {4, "DD", 9.0000M}},
category: 20
books: List<Book>() {Book {1, "AA", 19.0000M}, Book {2, "BB", 18.0000M}},
category: 30
books: List<Book>() {Book {3, "CC", 30.0000M}},
}
UPDATE
books.GroupBy(book => book.Price).Select(group => (group.Key, group.ToList()));
I can get grouped list of books but, can not group by multiple conditions.
CodePudding user response:
The GroupBy
operator expects a function or expression that returns the group key. You can use this to return the group "name" based on the price :
var bins=books.GroupBy(b=> b.Price switch {
<=10 =>"cheap",
>10 and <= 20 => " medium",
_ => "expensive"})
.ToDictionary(g=>g.Key,g=>g);
The result is a dictionary with each category and its contents :
Console.WriteLine(JsonSerializer.Serialize(bins));
-------
{
" medium":[{"Id":1,"Name":"AA","Price":19.0000},{"Id":2,"Name":"BB","Price":18.0000}],
"expensive":[{"Id":3,"Name":"CC","Price":30.0000}],
"cheap":[{"Id":4,"Name":"DD","Price":9.0000}]
}
I used pattern matching in GroupBy
to fit all conditions in a single lambda. This could be a separate function though :
string BookToBins(Book b)
{
if (b.Price <= 10) return "cheap";
if (b.Price <= 20) return "medium";
return "expensive";
}
...
var bins=books.GroupBy(BookToBins)
.ToDictionary(g=>g.Key,g=>g);
CodePudding user response:
First - add category to the list
var newBookList = BookList.Select(x=> new { Book = x,
Category = x.Price <= 10 ? 10 :
x.Price <= 20 ? 20 :
30 } ).ToList();
then Group By this Category :
var GroupedBooks = newBookList.GroupBy(x=>x.Category);
foreach(var category in GroupedBooks.Keys) {
Console.WriteLine("category : {0}", category);
foreach(var b in GroupedBooks[Keys].Select(x=>x.Book))
Console.Write("Book {0}, \"{1}\", {2}",b.Id, b.Name, b.Price);
}
something like that?
CodePudding user response:
With ternary conditional operator
books.GroupBy(b => b.Price < 10 ? 10 : (b.Price < 20 ? 20 : 30));