This is a simple question but I'm struggling to find an elegant solution. Let's say I have a simple data structure, the list of groups of items. Each group has a unique ID and each item has a unique ID, too.
I want to obtain a given item from a given group, if it exists, or null
otherwise. I've come up with two implementations, neither of which I really like:
public class Item
{
public int ItemId;
}
public class Group
{
public int GroupId;
public Item[] Items;
}
public static class Test
{
public static Item GetItemV1(this IEnumerable<Group> groups, int groupId, int itemId)
{
return groups.SelectMany(g => g.Items)
.FirstOrDefault(i => i.ItemId == itemId);
}
public static Item GetItemV2(this IEnumerable<Group> groups, int groupId, int itemId)
{
var group = groups.FirstOrDefault(g => g.GroupId == groupId);
if (group != null)
{
return group.Items.FirstOrDefault(i => i.ItemId == itemId);
}
return null;
}
}
Can it be done as a one-liner query, yet without redundant iterations of SelectMany
?
Currently your first option doesn't check for the group ID, but that's easily fixed:
return groups.Where(g => g.GroupId == groupId)
.SelectMany(g => g.Items)
.FirstOrDefault(i => i.ItemId == itemId);
Or if there's only going to be one group with a given ID, and you want to stop if you've found that group but not found the item:
return groups.Where(g => g.GroupId == groupId)
.Take(1) // Don't look through other groups after finding one match
.SelectMany(g => g.Items)
.FirstOrDefault(i => i.ItemId == itemId);
See more on this question at Stackoverflow