lifeformed
lifeformed

Reputation: 525

Need help simplifying a LINQ query: choosing an item of a preferred type

Can the following be done with a single LINQ expression? I have a list of Item:

public enum ItemType
{
    Top,
    Bottom,
    Side,
    CornerBottom,
    CornerTop
}

public class Item
{
    public int ID;
    public ItemType Type;
}

I want to select an Item based on the ItemType - however, there is a special case with CornerBottom and CornerTop. If I'm searching for a CornerBottom Item, and there are no such results, I would instead like a Bottom Item. If there are results for that, then I want a Side Item. Likewise with CornerTop, I prefer a CornerTop Item first, then Top second, then Side third.

Can this be done with a single expression? Right now I have a switch statement handling each ItemType. However, this is unwieldy, because in reality my Item class is more complicated (and I have more ItemTypes), and I have a lot of different queries that need this core functionality.

EDIT: Okay, my final solution is this. I reordered the ItemType enum with my preferred search order, as recommended by Spencer. Then I just put the custom comparison code in another function (which will be easy to reuse), and just orderby and return the first value.

ItemType searchType = ItemType.CornerTop;

var i = (from item in Items
        where typeCheck(item, searchType)
        orderby item.Type descending).FirstOrDefault();

bool typeCheck(Item item, ItemType type)
{
    switch (type)
    {
        case ItemType.CornerTop:
            return (item.Type == ItemType.CornerTop)
                || (item.Type == ItemType.Top)
                || (item.Type == ItemType.Side);
        case ItemType.CornerBottom:
            return (item.Type == ItemType.CornerBottom)
                || (item.Type == ItemType.Bottom)
                || (item.Type == ItemType.Side);
        default:
           return item.Type == type;
    }
}

Upvotes: 0

Views: 89

Answers (2)

AChudov
AChudov

Reputation: 214

You can construct two balanced trees. The first tree ordered by CornerTop -> Top -> Side. The second by CornerBottom -> Bottom -> Side. If you search CornerTop or CornerBottom you can grab the first item item in tree. If you search other type - you can search directly by log(N). On LINQ you can sort collection and grab the first or search by binary search algo.

Upvotes: 1

Spencer Ruport
Spencer Ruport

Reputation: 35117

Give each enum value a numeric value in the order of precedence. Sort your list of items by the Type and grab the first.

Upvotes: 2

Related Questions