1

I have two enums NAME and ALIAS which are guaranteed to have the same number of constants, and I need a way to convert each constant from NAME to its corresponding one from ALIAS, and vice-versa. For example:

def name_to_alias(name):
    if name == Name.PAUL:
        return Alias.STARCHILD
    elif name == Name.GENE:
        return Alias.DEMON
    ...

def alias_to_name(alias):
    if alias == Alias.STARCHILD:
        return Name.PAUL
    elif alias == Alias.DEMON:
        return Name.GENE
    ...

I don't wish to maintain two functions (or dicts) like these. Ideally, I'd have the enum mappings in a single data structure which I can access from both conversion functions.

I'm thinking of something like:

mappings = {
    Name.PAUL: Alias.STARCHILD
    Name.GENE: Alias.DEMON
    ...
}

This would work for converting from Name to Alias, but the opposite may have issues (what happens if I make a copy-paste error and end up with two dict keys with the same value?). Is there an easy and safe way to achieve this?

12
  • 3
    It sounds like you should get rid of the enums Commented Jul 1, 2024 at 15:46
  • 1
    @Martin That's surprising given you just guaranteed the two enum types have the exact same number of members - how did you compile Alias with colliding member names? Perhaps the mapping isn't as symmetric as you initially suggested? Commented Jul 1, 2024 at 15:51
  • 1
    Your editor (or ultimately the python runtime executing your code) will tell you there's a collision and you can then go back and fix your mistake. I'm afraid I don't understand what sloppy copy-pasting has to do with your question about mapping enum values. Can you tell us more about the relationship between Name and Alias? Is it 1-to-1, or many-to-1? Commented Jul 1, 2024 at 16:01
  • 1
    I guess that your function to get_name from alias should return all matching names, like def alias_to_name(alias): return [name for name, a in mappings.items() if a == alias] Commented Jul 1, 2024 at 16:04
  • 1
    @Martin I thought you were talking about making a reverse dictionary that would let you look up keys based on their values. Commented Jul 1, 2024 at 16:44

1 Answer 1

1

Considering that could occur that in mappings more than one name could have the same alias a safe function should raise an error, like

mappings = {
    Name.PAUL: Alias.STARCHILD,
    Name.GENE: Alias.DEMON,
    Name.PETER: Alias.CATMAN,
    Name.ALICE: Alias.DEMON
}

def alias_to_name(alias):
#check if the alias is more than once in the mappings and raise an error
    if list(mappings.values()).count(alias) > 1:
        raise ValueError('Alias is not unique', alias, [name for name, a in mappings.items() if a == alias])
    else:
        return [name for name, a in mappings.items() if a == alias]

That will output

('Alias is not unique', <Alias.DEMON: 2>, [<Name.GENE: 2>, <Name.ALICE: 4>])

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, that's what I was thinking. But I was expecting that a more "elegant" solution would exist, e.g. use a different data structure entirely, etc.
That's a linear search. Might be fine for short lists, but very costly for large ones. Not only that but the check for multiple aliases doubles the amount of work required.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.