繁体   English   中英

如何获得不区分大小写的 Python SET

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM