我有两套(虽然我可以做清单,或者其他):
a = frozenset(('Today','I','am','fine'))
b = frozenset(('hello','how','are','you','today'))
我想得到:
frozenset(['Today'])
或至少:
frozenset(['today'])
如果我小写我认为的所有内容,第二个选项是可行的,但我正在寻找一种更优雅的方式。是否可以
a.intersection(b)
以不区分大小写的方式?
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'])]
答案 0 :(得分:9)
这里的版本适用于任何一对迭代:
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]
示例:
print intersection('Today I am fine'.split(),
'Hello How a re you TODAY'.split(),
key=str.lower)
# -> [(['Today'], ['TODAY'])]
答案 1 :(得分:7)
不幸的是,即使您可以“随时更改”套装'项目(__lt__
和朋友 - 的比较相关特殊方法 - 实际上,只有__eq__
需要当前套装的方式实现,但这是一个实现细节) - 你不能,因为它们属于内置类型,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)
根据您表达的愿望,这会释放frozenset(['Today'])
。当然,在现实生活中,你可能想要做更多的覆盖(例如......:我在这里有事情的方式,cifrozenset
上的任何操作都返回普通frozenset
,失去了珍贵的案例独立特殊功能 - 您可能希望确保每次都返回cifrozenset
,并且虽然非常可行,但这并非无足轻重。)
答案 2 :(得分:3)
首先,你的意思是a.intersection(b)
吗?交集(如果不区分大小写)将为set(['today'])
。区别在于set(['i', 'am', 'fine'])
以下是两个想法:
1。)编写一个函数将两个元素的元素转换为小写,然后进行交集。这是你可以做到的一种方式:
>>> intersect_with_key = lambda s1, s2, key=lambda i: i: set(map(key, s1)).intersection(map(key, s2))
>>> fs1 = frozenset('Today I am fine'.split())
>>> fs2 = frozenset('Hello how are you TODAY'.split())
>>> intersect_with_key(fs1, fs2)
set([])
>>> intersect_with_key(fs1, fs2, key=str.lower)
set(['today'])
>>>
这不是很有效,因为必须在每次调用时创建转换和新集。
2.。)扩展frozenset
类以保持元素的不区分大小写的副本。重写intersection
方法以使用不区分大小写的元素副本。这会更有效率。
答案 3 :(得分:1)
>>> a_, b_ = map(set, [map(str.lower, a), map(str.lower, b)])
>>> a_ & b_
set(['today'])
或者......用较少的地图,
>>> a_ = set(map(str.lower, a))
>>> b_ = set(map(str.lower, b))
>>> a_ & b_
set(['today'])