Just override the add
method of your set.
from collections import MutableSet
class CasePreservingSet(MutableSet):
def __init__(self, *values):
self._values = {}
self._fold = str.casefold
for v in values:
self.add(v)
def __contains__(self, value):
return self._fold(value) in self._values
def __iter__(self):
return iter(self._values.values())
def __len__(self):
return len(self._values)
def add(self, value):
self._values[self._fold(value)] = value
def discard(self, value):
try:
del self._values[self._fold(value)]
except KeyError:
pass
ex:
In [1]: from caseinsensite import CasePreservingSet
In [2]: s = CasePreservingSet()
In [3]: s.add("ABC")
In [4]: s.add("abc")
In [5]: list(s)
Out[5]: ['abc']
In [6]: len(s)
Out[6]: 1
If you want to keep the case of the first entered element use this add method instead:
def add(self, value):
if self._fold(value) not in self._values:
self._values[self._fold(value)] = value
ex:
In [1]: from caseinsensite import CasePreservingSet
In [2]: s = CasePreservingSet()
In [3]: s.add("ABC")
In [4]: s.add("aBc")
In [5]: list(s)
Out[5]: ['ABC']
adapted from https://stackoverflow.com/a/27531275/8135079