How to Enumerate an Enum

How to enumerate an enum

foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Note: The cast to (Suit[]) is not strictly necessary, but it does make the code 0.5 ns faster.

How to enumerate an enum with String type?

Swift 4.2+

Starting with Swift 4.2 (with Xcode 10), just add protocol conformance to CaseIterable to benefit from allCases. To add this protocol conformance, you simply need to write somewhere:

extension Suit: CaseIterable {}

If the enum is your own, you may specify the conformance directly in the declaration:

enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }

Then the following code will print all possible values:

Suit.allCases.forEach {
print($0.rawValue)
}


Compatibility with earlier Swift versions (3.x and 4.x)

If you need to support Swift 3.x or 4.0, you may mimic the Swift 4.2 implementation by adding the following code:

#if !swift(>=4.2)
public protocol CaseIterable {
associatedtype AllCases: Collection where AllCases.Element == Self
static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
static var allCases: [Self] {
return [Self](AnySequence { () -> AnyIterator<Self> in
var raw = 0
var first: Self?
return AnyIterator {
let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
if raw == 0 {
first = current
} else if current == first {
return nil
}
raw += 1
return current
}
})
}
}
#endif

How can I iterate over an enum?

The typical way is as follows:

enum Foo {
One,
Two,
Three,
Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
Foo foo = static_cast<Foo>(fooInt);
// ...
}

Please note, the enum Last is meant to be skipped by the iteration. Utilizing this "fake" Last enum, you don't have to update your terminating condition in the for loop to the last "real" enum each time you want to add a new enum.
If you want to add more enums later, just add them before Last. The loop in this example will still work.

Of course, this breaks down if the enum values are specified:

enum Foo {
One = 1,
Two = 9,
Three = 4,
Last
};

This illustrates that an enum is not really meant to iterate through. The typical way to deal with an enum is to use it in a switch statement.

switch ( foo )
{
case One:
// ..
break;
case Two: // intentional fall-through
case Three:
// ..
break;
case Four:
// ..
break;
default:
assert( ! "Invalid Foo enum value" );
break;
}

If you really want to enumerate, stuff the enum values in a vector and iterate over that. This will properly deal with the specified enum values as well.

How to loop through all enum values in C#?

Yes you can use the ‍GetValue‍‍‍s method:

var values = Enum.GetValues(typeof(Foos));

Or the typed version:

var values = Enum.GetValues(typeof(Foos)).Cast<Foos>();

I long ago added a helper function to my private library for just such an occasion:

public static class EnumUtil {
public static IEnumerable<T> GetValues<T>() {
return Enum.GetValues(typeof(T)).Cast<T>();
}
}

Usage:

var values = EnumUtil.GetValues<Foos>();

How to programmatically enumerate an enum type?

This is the JavaScript output of that enum:

var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["First"] = 0] = "First";
MyEnum[MyEnum["Second"] = 1] = "Second";
MyEnum[MyEnum["Third"] = 2] = "Third";
})(MyEnum || (MyEnum = {}));

Which is an object like this:

{
"0": "First",
"1": "Second",
"2": "Third",
"First": 0,
"Second": 1,
"Third": 2
}

Enum Members with String Values

TypeScript 2.4 added the ability for enums to possibly have string enum member values. So it's possible to end up with an enum that look like the following:

enum MyEnum {
First = "First",
Second = 2,
Other = "Second"
}

// compiles to
var MyEnum;
(function (MyEnum) {
MyEnum["First"] = "First";
MyEnum[MyEnum["Second"] = 2] = "Second";
MyEnum["Other"] = "Second";
})(MyEnum || (MyEnum = {}));

Getting Member Names

We can look at the example immediately above to try to figure out how to get the enum members:

{
"2": "Second",
"First": "First",
"Second": 2,
"Other": "Second"
}

Here's what I came up with:

const e = MyEnum as any;
const names = Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);

Member Values

Once, we have the names, we can loop over them to get the corresponding value by doing:

const values = names.map(k => MyEnum[k]);

Extension Class

I think the best way to do this is to create your own functions (ex. EnumEx.getNames(MyEnum)). You can't add a function to an enum.

class EnumEx {
private constructor() {
}

static getNamesAndValues(e: any) {
return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as string | number }));
}

static getNames(e: any) {
return Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
}

static getValues(e: any) {
return EnumEx.getNames(e).map(n => e[n] as string | number);
}
}

How can I loop through enum values for display in radio buttons?

Two options:

for (let item in MotifIntervention) {
if (isNaN(Number(item))) {
console.log(item);
}
}

Or

Object.keys(MotifIntervention).filter(key => !isNaN(Number(MotifIntervention[key])));

(code in playground)


Edit

String enums look different than regular ones, for example:

enum MyEnum {
A = "a",
B = "b",
C = "c"
}

Compiles into:

var MyEnum;
(function (MyEnum) {
MyEnum["A"] = "a";
MyEnum["B"] = "b";
MyEnum["C"] = "c";
})(MyEnum || (MyEnum = {}));

Which just gives you this object:

{
A: "a",
B: "b",
C: "c"
}

You can get all the keys (["A", "B", "C"]) like this:

Object.keys(MyEnum);

And the values (["a", "b", "c"]):

Object.keys(MyEnum).map(key => MyEnum[key])

Or using Object.values():

Object.values(MyEnum)

Iterate Between Enum Values in C#

This will work:

for(Cars car=Cars.Opel; car<=Cars.Citroen; car++)
{
Console.WriteLine(car);
}

but you have to make sure that the start value is less than the end value.

EDIT

If you don't hardcode the start and end, but supply them as parameters, you need to use them in the correct order. If you just switch "Opel" and "Citroen", you will get no output.

Also (as remarked in the comments) the underlying integer values must not contain gaps or overlaps. Luckily if you do not specify values yourself (even the '=0' is not needed), this will be the default behaviour. See MSDN:

When you do not specify values for the elements in the enumerator list, the values are automatically incremented by 1.

How to iterate over enum

You can generates a list of cases on an enum with cases() like this:

enum Shapes
{
case RECTANGLE;
case SQUARE;
case CIRCLE;
case OVAL;
}

foreach (Shapes::cases() as $shape) {
echo $shape->name . "\n";
}

The output of this is:

RECTANGLE
SQUARE
CIRCLE
OVAL

for PHP 8.1 and greater.

See: PHP Fiddle



Related Topics



Leave a reply



Submit