我想知道是否有使用set()
参数实现key
的python函数,类似于例如key
中的sorted(iterable, *, key=None, reverse=False)
?
我认为此功能在某些情况下很有用,尤其是在比较自定义对象而不必更改其hash()
函数的情况下。
示例1
iterable = [1.0, 1.5, 2.0, 2.5]
x = set(iterable) # yields {1.0, 1.5, 2.0, 2.5}
y = set(iterable, key=math.floor) # yields {1.0, 2.0}
示例2
iterable = ['abc', 'ade', 'bbc', 'abc', 'bfg']
x = set(iterable) # yields {'abc', 'ade', 'bbc', 'bfg'}
y = set(iterable, key=lambda x: x[0]) # yields {'abc', 'bbc'}
我可以想象这将不会实现,因为如果发现重复对象,很难选择选择哪个对象。但是,这可以通过某些策略来克服,例如“选择第一”,“选择随机”,“选择最后”。
感谢您的所有答复,Daniel Roseman提出了针对该问题的最优雅的解决方案:
key = math.floor # Or any desired key function
y = set({key(i): i for i in iterable}.values())
答案 0 :(得分:3)
这基本上不是字典,键是将函数应用于值的结果吗?
y = {math.floor(i): i for i in iterable}
答案 1 :(得分:3)
您可以使用自定义类型来实现另一种方法:
class FlooredFloat:
def __init__(self, value):
self.value = value
def __hash__(self):
return hash(math.floor(self.value))
def __eq__(self, other):
return other.value == self.value
iterable = [1.0, 1.5, 2.0, 2.5]
x = set(map(FlooredFloat, iterable))
答案 2 :(得分:0)
您可以使其具有功能:
import itertools
import math
def strategy(items):
return items[0]
def set_with_key(iterable, key):
iterable = sorted(iterable, key=key)
groups = [list(x[1]) for x in itertools.groupby(iterable, key)]
return [strategy(items) for items in groups]
iterable = [1.0, 1.5, 2.0, 2.5]
print(set_with_key(iterable, math.floor))
iterable = ["abc", "ade", "bbc", "abc", "bfg"]
print(set_with_key(iterable, lambda x: x[0]))
答案 3 :(得分:0)
Daniel Roseman's observation使用字典非常出色。
如果从语法上讲,您需要看起来像键函数的东西,那么编写起来就很容易了:
def key(it, func):
seen=set()
for e in it:
x=func(e)
if x not in seen:
seen.add(x)
yield True
else:
yield False
然后,您可以对它(和zip
)使用集合理解:
>>> iterable = [1.0, 1.5, 2.0, 2.5]
>>> {x for x,y in zip(iterable, key(iterable, math.floor)) if y}
{1.0, 2.0}
>>> {x for x,y in zip(iterable, key(iterable, lambda s: s[0])) if y}
{'abc', 'bbc'}
您还可以这样编写函数:
def set_with_key(it, func):
seen=set()
return {e for e in iterable if func(e) not in seen and not seen.add(func(e))}
>>> set_with_key([1.0, 1.5, 2.0, 2.5], math.floor)
{1.0, 2.0}
>>> set_with_key(['abc', 'ade', 'bbc', 'abc', 'bfg'], lambda s: s[0])
{'abc', 'bbc'}