我需要根据键是大于还是小于给定值,将浮点列表或不同长度的(命名)元组列表分组。
例如,给定一个小于1的2的幂列表,以及一个截止列表:
twos = [2**(-(i+1)) for i in range(0,10)]
cutoffs = [0.5, 0.125, 0.03125]
然后功能
split_into_groups(twos, cutoffs)
应该返回
[[0.5], [0.25, 0.125], [0.0625, 0.03125], [0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625]]
我已经实现了这样的功能:
def split_by_prob(items, cutoff, groups, key=None):
for k,g in groupby(enumerate(items), lambda (j,x): x<cutoff):
groups.append((map(itemgetter(1),g)))
return groups
def split_into_groups(items, cutoffs, key=None):
groups = items
final = []
for i in cutoffs:
groups = split_by_prob(groups,i,[],key)
if len(groups) > 1:
final.append(groups[0])
groups = groups.pop()
else:
final.append(groups[0])
return final
final.append(groups)
return final
目前通过的测试是:
>>> split_by_prob(twos, 0.5, [])
[[0.5], [0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625]]
>>> split_into_groups(twos, cutoffs)
[[0.5], [0.25, 0.125], [0.0625, 0.03125], [0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625]]
>>> split_into_groups(twos, cutoffs_p10)
[[0.5, 0.25, 0.125], [0.0625, 0.03125, 0.015625], [0.0078125, 0.00390625, 0.001953125], [0.0009765625]]
cutoffs_p10 = [10**(-(i+1)) for i in range(0,5)]
我可以直接将其扩展为
形式的元组列表items = zip(range(0,10), twos)
改变
def split_by_prob(items, cutoff, groups, key=None):
for k,g in groupby(enumerate(items), lambda (j,x): x<cutoff):
groups.append((map(itemgetter(1),g)))
return groups
到
def split_by_prob(items, cutoff, groups, key=None):
for k,g in groupby(enumerate(items), lambda (j,x): x[1]<cutoff):
groups.append((map(itemgetter(1),g)))
return groups
如何通过添加默认为浮点数(或整数等)的键来扩展原始方法,但是可以处理元组和命名元组的键?
例如:
split_into_groups(items, cutoffs, key=items[0])
将返回
[[(0,0.5)], [(1,0.25), (2,0.125)], [(3,0.0625), (4,0.03125)], [(5,0.015625), (6,0.0078125), (7,0.00390625), (8,0.001953125), (9,0.0009765625)]]
答案 0 :(得分:1)
在我的回答中,我假设,截止日期以递增顺序结束 - 只是为了简化情况。
Discriminator
检测到一个插槽class Discriminator(object):
def __init__(self, cutoffs):
self.cutoffs = sorted(cutoffs)
self.maxslot = len(cutoffs)
def findslot(self, num):
cutoffs = self.cutoffs
for slot, edge in enumerate(self.cutoffs):
if num < edge:
return slot
return self.maxslot
grouper
将项目放入广告位from collections import defaultdict
def grouper(cutoffs, items, key=None):
if not key:
key = lambda itm: itm
discr = Discriminator(cutoffs)
result = defaultdict(list)
for item in items:
num = key(item)
result[discr.findslot(num)].append(item)
return result
def split_into_groups(cutoffs, numbers, key=None):
groups = grouper(cutoffs, numbers, key)
slot_ids = sorted(groups.keys())
return [groups[slot_id] for slot_id in slot_ids]
grouper
建议的判别器甚至适用于未分类的物品。
key
事实上,提供key
功能比原来看起来更容易。
它只是一个通过参数提供的函数,因此它成为转换函数的别名,用于调用获取值,我们想用于比较,分组等。
有None
的特殊情况,对于这种情况,我们必须使用一些身份功能。
最简单的是
func = lambda itm: itm
注意:上面的所有函数都是通过测试套件测试的(包括使用key
函数,但是我把它从这个答案中删除了,因为它变得太长了。