[英]How to get Case Insensitive Python SET
我有一个字符串列表:
In [53]: l = ['#Trending', '#Trending', '#TrendinG', '#Yax', '#YAX', '#Yax']
In [54]: set(l)
Out[54]: {'#TrendinG', '#Trending', '#YAX', '#Yax'}
我想有一个不区分大小写的set
这个名单的。
预期结果:
Out[55]: {'#Trending', '#Yax'}
我怎样才能做到这一点?
如果您需要保留大小写,则可以改用字典。 对键进行大小写折叠,然后将值提取到一个集合中:
set({v.casefold(): v for v in l}.values())
str.casefold()
方法使用Unicode 大小写折叠规则(pdf)来规范化字符串以进行不区分大小写的比较。 这对于非 ASCII 字母和带有连字的文本尤其重要。 例如德语ß
S ,它被归一化为ss
,或者,来自同一种语言, s
long s :
>>> print(s := 'Waſſerſchloß', s.lower(), s.casefold(), sep=" - ")
Waſſerſchloß - waſſerſchloß - wasserschloss
您可以将其封装到一个类中。
如果您不关心保留大小写,只需使用集合理解:
{v.casefold() for v in l}
请注意,Python 2 没有此方法,在这种情况下使用str.lower()
。
演示:
>>> l = ['#Trending', '#Trending', '#TrendinG', '#Yax', '#YAX', '#Yax']
>>> set({v.casefold(): v for v in l}.values())
{'#Yax', '#TrendinG'}
>>> {v.lower() for v in l}
{'#trending', '#yax'}
将第一种方法包装到一个类中看起来像:
try:
# Python 3
from collections.abc import MutableSet
except ImportError:
# Python 2
from collections import MutableSet
class CasePreservingSet(MutableSet):
"""String set that preserves case but tests for containment by case-folded value
E.g. 'Foo' in CasePreservingSet(['FOO']) is True. Preserves case of *last*
inserted variant.
"""
def __init__(self, *args):
self._values = {}
if len(args) > 1:
raise TypeError(
f"{type(self).__name__} expected at most 1 argument, "
f"got {len(args)}"
)
values = args[0] if args else ()
try:
self._fold = str.casefold # Python 3
except AttributeError:
self._fold = str.lower # Python 2
for v in values:
self.add(v)
def __repr__(self):
return '<{}{} at {:x}>'.format(
type(self).__name__, tuple(self._values.values()), id(self))
def __contains__(self, value):
return self._fold(value) in self._values
def __iter__(self):
try:
# Python 2
return self._values.itervalues()
except AttributeError:
# Python 3
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
使用演示:
>>> cps = CasePreservingSet(l)
>>> cps
<CasePreservingSet('#TrendinG', '#Yax') at 1047ba290>
>>> '#treNdinG' in cps
True
您可以使用lower()
:
>>> set(i.lower() for i in l)
set(['#trending', '#yax'])
您可以在创建集合之前将整个列表转换为小写。
l = map(lambda s: s.lower(), l)
set(l)
创建您自己的不区分大小写的set
类。
class CaseInsensitiveSet(set):
def add(self, item):
try:
set.add(self, item.lower())
except Exception: # not a string
set.add(self, item)
def __contains__(self, item):
try:
return set.__contains__(self, item.lower())
except Exception:
return set.__contains__(self, item)
# and so on... other methods will need to be overridden for full functionality
即使每个答案都使用 .lower(),您想要的输出也会大写。
为了实现它,你可以这样做:
l = ['#Trending', '#Trending', '#TrendinG', '#Yax', '#YAX', '#Yax']
l = set(i[0]+i[1:].capitalize() for i in l)
print l
输出:
set(['#Trending', '#Yax'])
另一种选择是使用multidict
库中的istr
(不区分大小写的 str)对象:
In [1]: from multidict import istr, CIMultiDict
In [2]: s = {'user-agent'}
In [5]: s = CIMultiDict({istr(k): None for k in {'user-agent'}})
In [6]: s
Out[6]: <CIMultiDict('User-Agent': None)>
In [7]: 'user-agent' in s
Out[7]: True
In [8]: 'USER-AGENT' in s
Out[8]: True
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.