This is my sample code:
var users = GetUsers();
var userGroups = users.GroupBy(x => x.Id);
foreach (var userGroup in userGroups)
{
var user = userGroup.First();
var carriedItems = userGroup.Select(x => x.CarriedItemId).ToList();
Console.WriteLine($"UserId={user.Id}, CarriedItemsCount={carriedItems.Count}");
}
static IEnumerable<User> GetUsers()
{
return new List<User>()
{
new User() { Id = 1, CarriedItemId = new List<int> { 6 }},
new User() { Id = 1, CarriedItemId = new List<int> { 12 }},
new User() { Id = 2, CarriedItemId = new List<int> { 2 }},
new User() { Id = 3, CarriedItemId = new List<int>() }
};
}
class User
{
public int Id { get; set; }
public List<int> CarriedItemId { get; set; }
}
Output of this is:
UserId=1, CarriedItemsCount=2
UserId=2, CarriedItemsCount=1
UserId=3, CarriedItemsCount=1
Why UserId=3
has 1 carried item, but not 0? After debugging I can see, that his carriedItems
list contains default int32
value, which is 0. Why? I expected his carriedItems
list to be empty. Can someone spot a bug?
CodePudding user response:
var carriedItems = userGroup.Select(x => x.CarriedItemId).ToList();
Console.WriteLine($"UserId={user.Id}, CarriedItemsCount={carriedItems.Count}");
carriedItems is not the count of CarriedItemId, its a list of each entry of the usergroup with that ID. The one for id = 3 has 1 entry that contains 0.
CodePudding user response:
You've messed up types and ranges. Your code as it is does not Count the things you think it does. Right now, it counts Collections. Not Items. See comments below:
class User
{
public int Id { get; set; }
// this 'CarriedItemId' is a LIST, so it's rather a "CarriedItemIds"
public List<int> CarriedItemId { get; set; }
}
var users = GetUsers();
var userGroups = users.GroupBy(x => x.Id);
foreach (var userGroup in userGroups)
{
var user = userGroup.First();
// watch carefully what you select here
// CarriedItemId is a LIST, not a single item
// 'carriedItems' is a List<List<int>>
var carriedItems = userGroup.Select(x => x.CarriedItemId).ToList();
Console.WriteLine($"UserId={user.Id}, CarriedItemsCount={carriedItems.Count}");
}
Therefore, for a userId=3, there's one record, that record has an item list, which, although empty, is still a list, and record exists, so you get a 1.
To get a merged set of all itemIds, use SelectMany instead:
var carriedItems = userGroup.SelectMany(x => x.CarriedItemId).ToList();
This will merge all CarriedItemId
from all User
records, and you will end up with expected 2/1/0 counts.