Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate through enum type while skipping some values?

The key part of my question is the skipping. I plan to use an enum type that has about 20 elements. I want to iterate through this set but need to skip an element or two each time. What to skip is known in advance. A comparable example is the enum type that consists of all letters of the alphabet, and when iterating, I want to skip all the vowels.

How should I code the iteration in an elegant/efficient way? Should I make a separate set of elements consisting of vowels? I have no code to show because I am just thinking about the problem.

like image 268
RJIGO Avatar asked Mar 12 '12 17:03

RJIGO


People also ask

How do I iterate over an enum?

Enums don't have methods for iteration, like forEach() or iterator(). Instead, we can use the array of the Enum values returned by the values() method.

Can you loop through an enum C ++?

Yes. It iterates over an std::initializer_list<Item>. link.

Can enum take float values?

Enums can only be ints, not floats in C# and presumably unityScript.

Can you loop through enum Java?

Enumeration (enum) in Java is a datatype which stores a set of constant values. You can use enumerations to store fixed values such as days in a week, months in a year etc. You can iterate the contents of an enumeration using for loop, using forEach loop and, using java.


2 Answers

var query = Enum.GetValues(typeof(MyEnum))
    .Cast<MyEnum>()
    .Except(new MyEnum[] { MyEnum.A, MyEnum.E });
foreach (MyEnum item in query) {
    ...
}

You need to cast in order to get the magic of LINQ. Except alone will not do it.


UPDATE:

I got another idea. You can define the enum with the FlagsAttribute and define the regular values as powers of 2, what is most easily achieved with the bitwise shift left operator <<. Starting with C# 7.0, you can also use binary literals like 0b_0000_0000_0010_0000. Then it is possible to combine existing values to form new values.

[Flags]
enum MyEnum
{
    None = 0,
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    E = 1 << 4,
    ...
    X = 1 << 23,
    Y = 1 << 24,
    Z = 1 << 25,
    Vowels = A | E | I | O | U
}

Now, you can formulate the query like this

IEnumerable<MyEnum> query = Enum.GetValues(typeof(MyEnum))
    .Cast<MyEnum>()
    .Where(x => (x & MyEnum.Vowels) == MyEnum.None);
foreach (MyEnum item in query) {
    ...
}

The advantage over the first solution is, that you can perform the test with a single bitwise AND-operation.

You can define up to 32 powers of two. If you need more, you can define the base type of the enum as long and use up to 64 flag values (plus combinations of existing flag values).

[Flags]
enum MyEnum : long
{
    ...
}
like image 192
Olivier Jacot-Descombes Avatar answered Sep 20 '22 09:09

Olivier Jacot-Descombes


I would make a separate set of elements consisting of vowels, and then take the set difference between the two sets using LINQ.

int[] vowels = {Letters.A, Letters.E, Letters.I, Letters.O, Letters.U};
IEnumerable<int> consonant = Enum.GetValues(typeof(Letters)).Except(vowels);
foreach (int consonant in consonants)
{
    // Do something with each consonant
}
like image 43
Adam Mihalcin Avatar answered Sep 18 '22 09:09

Adam Mihalcin