我有一个字典将一个整数范围映射到另一个整数范围,例如:
data = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 6, 9: 7, 10: 8}
我想找到值中数值区间无法递增的所有区域,因此我的输出应为:
result = [[6, 8]]
对于上述输入。
我认为我的答案将涉及here所述的分组itertools配方。我试图为我的目的做一个简单的实现,但我不确定如何将结果转换为我想要的结果:
from operator import itemgetter
from itertools import groupby
data = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 6, 9: 7, 10: 8}
for k, pos in groupby(enumerate(data.iteritems()), lambda (i, (a, s)):i - s):
print map(itemgetter(1), pos)
有输出:
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]
[(7, 6)]
[(8, 6), (9, 7), (10, 8)]
这适当地对我的输入数据进行分组,但并没有真正给出我想要的间隔。我在将此输出解析为我想要的间隔时看到的挑战是它为我提供了跳过区域的间隔'。
答案 0 :(得分:2)
假设"非增加"值在这些区域中保持不变,也不会减少,您可以只对具有相同值的条目进行分组,然后选择具有多个条目的组。最后,提取开始和结束索引。
>>> data = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 6, 9: 7, 10: 8}
>>> items = sorted(data.items())
>>> groups = itertools.groupby(items, key=operator.itemgetter(1))
>>> ranges = [grp for grp in (list(grp) for key, grp in groups) if len(grp) > 1]
>>> ranges
[[(6, 6), (7, 6), (8, 6)]]
>>> [(r[0][0], r[-1][0]) for r in ranges]
[(6, 8)]
答案 1 :(得分:1)
如果是这样的情况:(a)你的键是连续的整数,(b)你想要找到那些值不大于对应于前面的整数或的值的键不小于对应于连续整数的值,则为:
>>> [k for k in sorted(data.keys()) if (k-1 in data and not data[k-1] < data[k]) or (k+1 in data and not data[k] < data[k+1])]
[6, 7, 8]
答案 2 :(得分:0)
以下是使用defaultdict
的替代方法。
from collections import defaultdict
ranges = defaultdict(list)
data = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 6, 9: 7, 10: 8}
for index, num in data.iteritems():
ranges[num].append(index)
print [(r[0], r[-1]) for r in ranges.itervalues() if len(r) > 1]
这种方法的一个优点是它不需要对字典进行排序。
答案 3 :(得分:0)
这样的事情:
data = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 6, 9: 7, 10: 8}
sd = sorted(data.items())
result = []
for i in range(1, len(sd)):
if sd[i][1] == sd[i-1][1]:
result.append(i)
我认为sorted(data.items())
对你的循环来说更清晰,更具有pythonic性能
这给出了结果:
print result
[7, 8]
那可能是一个好的开始?