Python中集合的不区分大小写的比较

Ada*_*son 4 python django compare

我有两套(虽然我可以做清单,或其他):

a = frozenset(('Today','I','am','fine'))
b = frozenset(('hello','how','are','you','today'))
Run Code Online (Sandbox Code Playgroud)

我想得到:

frozenset(['Today'])
Run Code Online (Sandbox Code Playgroud)

或至少:

frozenset(['today'])
Run Code Online (Sandbox Code Playgroud)

第二种选择是可行的,如果我小写我认为的一切,但我正在寻找一种更优雅的方式.有可能吗?

a.intersection(b) 
Run Code Online (Sandbox Code Playgroud)

以不区分大小写的方式?

Django中的快捷方式也很好,因为我正在使用该框架.

下面的交集方法示例(我无法弄清楚如何在注释中获取此格式):

print intersection('Today I am fine tomorrow'.split(),
                    'Hello How a re you TODAY and today and Today and Tomorrow'.split(),
                    key=str.lower)

[(['tomorrow'], ['Tomorrow']), (['Today'], ['TODAY', 'today', 'Today'])]
Run Code Online (Sandbox Code Playgroud)

jfs*_*jfs 10

这里的版本适用于任何一对迭代:

def intersection(iterableA, iterableB, key=lambda x: x):
    """Return the intersection of two iterables with respect to `key` function.

    """
    def unify(iterable):
        d = {}
        for item in iterable:
            d.setdefault(key(item), []).append(item)
        return d

    A, B = unify(iterableA), unify(iterableB)

    return [(A[k], B[k]) for k in A if k in B]
Run Code Online (Sandbox Code Playgroud)

例:

print intersection('Today I am fine'.split(),
                   'Hello How a re you TODAY'.split(),
                   key=str.lower)
# -> [(['Today'], ['TODAY'])]
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 8

不幸的是,即使你可以"随时改变"集合项目的比较相关的特殊方法(__lt__和朋友 - 实际上,只__eq__需要当前实现集合的方式,但这是一个实现细节) - 你可以"T,因为它们属于一个内置式,str-这是不够的,因为__hash__同样重要的,并通过你想要做你的交集它已经被应用的时候,把套"项目在不同的散列桶从他们需要最终以你想要的方式工作(即,不能保证'今天'和'今天'在同一个桶中).

所以,为了你的目的,你不可避免地需要建立新的数据结构 - 如果你认为它"不优雅"必须要做到这一点,那你就好运了:内置的套装只是不随身携带允许人们改变比较和散列函数所需的巨额行李和开销,这将使得需要的事情膨胀10倍(或更多),并且可能在一百万个用例中感受到.

如果您经常需要与不区分大小写的比较相关联,那么您应该考虑子类化或包装str(覆盖比较和散列)以提供"不区分大小写的str"类型cistr- 然后,当然,请确保只有实例cistr(例如) )添加到你感兴趣的集合(&c)(通过子类化set和c,或者只是通过小心).举一个简单的例子......:

class ci(str):
  def __hash__(self):
    return hash(self.lower())
  def __eq__(self, other):
    return self.lower() == other.lower()

class cifrozenset(frozenset):
  def __new__(cls, seq=()):
    return frozenset((ci(x) for x in seq))

a = cifrozenset(('Today','I','am','fine'))
b = cifrozenset(('hello','how','are','you','today'))

print a.intersection(b)
Run Code Online (Sandbox Code Playgroud)

frozenset(['Today'])根据你表达的愿望,这确实会发出.当然,在现实生活中,你可能想要做更多的事情(例如......:我在这里拥有东西的方式,任何操作都cifrozenset返回平原frozenset,失去珍贵的案例独立特色 - 你会可能想要确保cifrozenset每次都返回a ,而且,虽然非常可行,但这并不是微不足道的.