我有一个两个元素元组的列表,每个元组的第一个元素是一个整数,这些元组等价于键值对,实际上这些元组是扁平化的dict_items
,使用list(d.items())
生成。
第一个位置的元素保证是唯一的(它们是键),并且有很多键值对,其中值是相同的,并且键在连续范围内,这意味着有很多连续的键值对,其中一个键等于前一个键加1。
我想把这些对分成三个一组,其中前两个元素是整数,是这样的连续对的开始和结束,第三个元素是值。
逻辑很简单,如果输入是[(0, 0), (1, 0), (2, 0)]
,输出应该是[(0, 2, 0)]
,第一个数字是键范围的开始,第二个数字是键范围的结束,第三个是值。0、1、2是连续的整数。
给定[(0, 0), (1, 0), (2, 0), (3, 1), (4, 1)]
,输出应为[(0, 2, 0), (3, 4, 1)]
,具有相同值的连续键被分组。
给定[(0, 0), (1, 0), (2, 0), (3, 1), (4, 1), (5, 2), (7, 2), (9, 2)]
,输出应该是[(0, 2, 0), (3, 4, 1), (5, 5, 2), (7, 7, 2), (9, 9, 2)]
,因为5,7,9不是连续的整数,5 + 1 != 7 and 7 + 1 != 9
。
输入:
[(3, 0),
(4, 0),
(5, 0),
(6, 2),
(7, 2),
(8, 2),
(9, 2),
(10, 2),
(11, 2),
(12, 2),
(13, 1),
(14, 1),
(15, 3),
(16, 3),
(17, 3),
(18, 3),
(19, 3),
(20, 3),
(21, 3),
(22, 3),
(23, 3),
(24, 3),
(25, 3),
(26, 3),
(27, 1),
(28, 1)]
字符串
输出量:
[(3, 5, 0), (6, 12, 2), (13, 14, 1), (15, 26, 3), (27, 28, 1)]
型
我的代码给出了正确的输出,但效率不高:
def group_numbers(numbers):
l = len(numbers)
i = 0
output = []
while i < l:
di = 0
curn, curv = numbers[i]
while i != l and curn + di == numbers[i][0] and curv == numbers[i][1]:
i += 1
di += 1
output.append((curn, numbers[i - 1][0], curv))
return output
型
生成测试用例的代码:
def make_test_case(num, lim, dat):
numbers = {}
for _ in range(num):
start = random.randrange(lim)
end = random.randrange(lim)
if start > end:
start, end = end, start
x = random.randrange(dat)
numbers |= {n: x for n in range(start, end + 1)}
return sorted(numbers.items())
型
如何更有效地做到这一点,例如使用itertools.groupby
?
答案需要根据我的正确方法进行验证。
请注意,输入中可能存在没有值的空白,我想使问题简短,所以我没有包括这样的测试用例,但确实知道不应该填充这样的空白。更有效的方法应该产生与我相同的输出。
一个手动测试用例来证明这一点:
In [35]: group_numbers([(0, 0), (1, 0), (2, 0), (3, 0), (10, 1), (11, 1), (12, 1), (13, 1)])
Out[35]: [(0, 3, 0), (10, 13, 1)]
型
注解中建议的测试用例的说明,预期输出为:
In [61]: group_numbers([(3, 0), (5, 0), (7, 0)])
Out[61]: [(3, 3, 0), (5, 5, 0), (7, 7, 0)]
型[(1, 0), (1, 1), (2, 0)]
的输出应该是未定义的,如果遇到它应该会引发异常。这样的输入不是有效的输入。正如您在生成示例的代码中看到的,所有数字只能有一个值。[(1, 0), (3, 0), (5, 0)]
的输出是[(1, 1, 0), (3, 3, 0), (5, 5, 0)]
。
编辑
我不是一个以英语为母语的人,事实上,我一般不擅长语言(虽然希望不是编程语言),而且我没有人际交往能力(我真的没有人可以交谈),所以我的问题最初可能会令人困惑,我担心如果我把它写得很长,它肯定会包含语法错误。
我已经编辑了我的问题,以包括更多的细节,并更彻底地解释事情,希望使问题不那么混乱。
2条答案
按热度按时间pod7payv1#
考虑到所有修改,为了通过考虑所有条件来保证正确的输出,您可以使用以下解决方案:
字符串
OP测试用例:
型
旧答案(使用itertools,不考虑最后一种情况)
只需使用
itertools.groupby
,您就可以做到这一点:型
如果没有
operator.itemgetter
,则是:型
OP测试用例(假设解定义为函数
group_numbers
):型
m2xkgtsf2#
使用生成器函数,该生成器函数基于算术和检查元组的第一元素的连续(升序)范围:
个字符