Question

I have enum like this

[Flags]
public enum Key
{
  None = 0,
  A = 1,
  B = 2,
  C = 4
}

I have the following

Key k1 = Key.A | Key.B | Key.C;

I want to get the key in k1 that has the lowest value. How can I do that?

Example:

Key k1 = Key.A | Key.B | Key.C; // I want a 
Key k2 = Key.B | Key.C; // I want b
Key k3 = Key.A | Key.C; // I want a
Was it helpful?

Solution

Keys key = Keys.b | Keys.c;

var lowest = Enum.GetValues(typeof(Keys))
    .Cast<Keys>()
    .OrderBy(x => x)
    .FirstOrDefault(x => key.HasFlag(x));

Slightly more efficient and .NET 4.0-ish version of the LINQ method.

OTHER TIPS

You can use a bit trick:

Key key = Key.B | Key.C;
Key lowest = (Key)((int)key & -(int)key);
Keys key = Keys.b | Keys.c;

var lowest = Enum.GetValues(typeof(Keys))
    .OfType<Keys>()
    .Where(x => (x & key) != 0)
    .OrderBy(x => x)
    .DefaultIfEmpty((Keys)0);

Console.WriteLine(lowest);

If you have only 3 values in the enum probably the fastest and easiest is to check them one by one. For a general solution, however, you might want to try to convert the value of k1 to integer, find the largest power of 2 that divides it and convert it back to Keys enum value.

  1. Get a list of all the values in the enum
  2. Map those values to some kind of comparable data type
  3. Compare all the values and keep track of the lowest one
  4. Convert the lowest one back to the enum type

Needs to be an iterative implementation where you test bits. I would do something like this.

unsigned int k = (unsigned int) k1;
int pos = -1;
while (k) {
   pos++;
   if (k & 0x1) break;
   k >>= 1;
}
Keys lowestKey = 0;
if (pos >= 0) lowestKey = 0x1 << pos;

The code you originally posted doesn't make sense: a+b+c aren't prefixed by a type-name, so they won't refer to the enum names they seem to be intended to refer to.

Also, if you use a bitwise AND to combine flags, the result will contain all flags on in all paramters - in this case, none.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top