简体   繁体   中英

ORDER BY C# Enum Flags most matches

Given the following Enum:

[Flags]
public enum CheeseCharacteristic 
{
    Yellow = 1,
    Stinks = 2,
    Squeaks = 4,
    Holey = 8,
    Mouldy = 16,
    UseOnToast = 32
}

And an entity Cheese having the property Characteristic , is it possible to order Cheeses based on how many flags are matched against the Characteristic ? For example, say a Stilton has the Characteristic value Yellow , Stinks , Mouldy and a MildCheddar has the Characteristic value Yellow , UseOnToast , is it possible to order by the number of matches for a given query?

So if I want to compare a collection of Cheese entities against Yellow , Mouldy then both Stilton and MildCheddar are returned, but the Stilton is top of the list as it has 2 matches.

To take this further, if I store the enum value in SQL Server, can I perform this sort in the DB using EF Core?

This should work but not with EF

public class Cheese
{
    public string Name { get; }

    public CheeseCharacteristic Characteristic { get; }

    public Cheese(string name, CheeseCharacteristic characteristic)
    {
        Name = name;
        Characteristic = characteristic;
    }
}

public class Program
{
    private readonly static int[] CheeseCharacteristicValues =
        Enum.GetValues(typeof(CheeseCharacteristic)).Cast<int>().ToArray();

    public static void Main()
    {
        var pattern = CheeseCharacteristic.Yellow | CheeseCharacteristic.Mouldy;

        var cheeses = new List<Cheese>()
        {
            new Cheese("Camembert", CheeseCharacteristic.Stinks),

            new Cheese("MildCheddar", 
                CheeseCharacteristic.Yellow | CheeseCharacteristic.UseOnToast),

            new Cheese("Stilton", 
                CheeseCharacteristic.Yellow | CheeseCharacteristic.Stinks |
                CheeseCharacteristic.Mouldy),
        };

        IEnumerable<Cheese> sortedCheeses = 
            cheeses.OrderByDescending(c => GetFlagCount(c.Characteristic & pattern));
        ...
    }

    private static int GetFlagCount(CheeseCharacteristic characteristic) => 
        CheeseCharacteristicValues.Count(v => ((int)characteristic & v) == v);
}

Note that the enum values are extracted to a static variable to avoid extracting them (and create an array instance) each time GetFlagCount is executed.

Link to Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM