如何获取不区分大小写的Python集

2024-05-29 05:14:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个字符串列表:

In [53]: l = ['#Trending', '#Trending', '#TrendinG', '#Yax', '#YAX', '#Yax']

In [54]: set(l)
Out[54]: {'#TrendinG', '#Trending', '#YAX', '#Yax'}

我想有一个不区分大小写的set这个列表。

预期结果:

Out[55]: {'#Trending', '#Yax'}

我怎样才能做到这一点?


Tags: 字符串in列表out区分settrendingyax
3条回答

在创建集合之前,可以将整个列表转换为小写。

l = map(lambda s: s.lower(), l)
set(l)

如果你需要保留大小写,你可以用字典代替。大小写折叠键,然后将值提取到一个集合:

 set({v.casefold(): v for v in l}.values())

^{} method使用Unicode case folding rules (pdf)规范化字符串以进行不区分大小写的比较。这对于非ASCII字母和带连字的文本尤其重要。E、 g.德语^{} sharp S,标准化为ss,或者,来自同一语言的^{} 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):
    def __init__(self, *values):
        self._values = {}
        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'])

相关问题 更多 >

    热门问题