循环列表索引

cycling around a list indices

提问人:Talal Ghannam 提问时间:5/2/2023 最后编辑:Nathaniel FordTalal Ghannam 更新时间:5/3/2023 访问量:108

问:

我有一个整数列表,并指定了一个数字。我需要编写一个函数,使它接受 的第一个元素,其索引是 ,添加后续元素,直到 (在我们的例子中为 ,所以 , ),并将其作为另一个列表的第一个元素返回,并对后续元素执行相同的操作。诀窍是,我们需要在 when or are 中循环列表。L = [1, 2, 3, 4, 5]xL0xj+1j+2Rj+1j+x> len(L)

例如;

R = [5 (2+3), 7 (3+4), 9 (4+5), 6 (5+1), 3 (1+2)]

当 ,比如说,我们向后走而不是向前走。所以.x < 0-2j-1j-x

我为 x>0 编写了以下代码,但是我在索引方面遇到了问题。

def decode(L, x):
    R = []

    if x > 0:
        for j in L:
            i1 = L.index(j)+1-len(L)
            i2 = L.index(j)+x-len(L)

            R[L.index(j)] = sum(L[i1:i2])+L[i2]

    return R

当 is negative 和 is or positive 时,就会发生问题,这将返回一个空列表。i1i20

Python 列表 切片

评论

3赞 Scott Hunter 5/2/2023
你能提供更具体的例子吗?例如,什么应该返回,为什么?decode(L,3)
0赞 Mark Reed 5/2/2023
是的,我也不明白问题陈述。x 到底代表什么?你只是把列表的前 x 个元素加在一起吗?
0赞 Talal Ghannam 5/2/2023
x 表示在元素 j 之后需要求和的元素数。因此,对于 x = 3,对于 1 的第一个元素,您需要将 2+3+4 = 9 求和,对于元素 2,后续的三个元素是 3、4、5,它们的总和是 12,依此类推。问题是,当您在列表末尾有部分序列,而在开头有剩余部分时。例如,对于 j = 4,您需要求和的序列是 5 + 1 +2 = 8。因此,您需要从头开始循环列表 (1+2)。R 应为 [9, 12, 10, 8, 6]。

答:

0赞 Alain T. 5/2/2023 #1

您可以使用 itertools 函数来遍历值,而不必为索引而烦恼。该函数将自动为您环绕列表元素。该函数允许您从特定偏移量 (x) 进行迭代。该函数可以随时构建总计,从而避免了添加列表下标的需要(即从累积总和之间的差异中工作):cycleisliceaccumulate

from itertools import accumulate,cycle,islice,tee

def decode(L,x):
    S1,S2 = tee(accumulate(cycle(L)),2)     # cumulative sums
    S2    = islice(S2,x,None)               # offset end from start
    return [e-s for _,s,e in zip(L,S1,S2)]  # sub-sums are differences

L = [1,2,3,4,5]

print(decode(L,2))
[5, 7, 9, 6, 3]

print(decode(L,3))
[9, 12, 10, 8, 6]

对于 x = 2,S1 和 S2 将通过 zip() 组合,以匹配开始 (s) 和结束 (n) 累积值,其差值对应于两者之间的数字之和:

L     :       1,  2,  3,  4,  5
S1 (s):       1,  3,  6, 10, 15, ...
S2 (e): 1, 3, 6, 10, 15, 16, 18, ...
e-s   : ..... 5,  7,  9,  6,  3   
          ^
          first 2 of S2 skipped by islice() 

注意:对于 x 的负值,您可以反转列表或将 len(L) 添加到小岛的偏移量中,具体取决于您期望输出的顺序(即它是以相反的顺序还是简单地添加前面的数字而不是后面的数字)

[编辑]为了在没有库的情况下执行此操作,您可以构建一个实际的累积值列表,并在该累积列表的下标上使用相同的方法,该累积列表的偏移量为 x 个位置:

def decode(L,x):
    S = L[:1]
    S.extend(S[-1]+n for n in L[1:] + L)     # cumulative sums
    return [e-s for _,s,e in zip(L,S,S[x:])] # offset differences

为了涵盖 x 的所有可能值,直到列表的长度,您需要累积总和的长度是输入列表的两倍

如果您不介意多次添加相同的项目来获得总和,您可以简单地将列表加倍并在子范围内使用正索引。重复的内容将具有与环绕相同的效果:

def decode(L,x):
    if x<0: return decode(L[::-1],-x)[::-1] 
    return [ sum((L*2)[i+1:i+1+x]) for i in range(len(L))]

我添加了负 x 过程作为如何使用相同(正)逻辑管理它的示例

评论

0赞 Talal Ghannam 5/2/2023
感谢您的代码,但是,必须在不导入 IterTools 等库的情况下解决问题。
0赞 Timus 5/2/2023
@TalalGhannam 那么请在问题中这么说,否则你就是在浪费提供答案的用户的时间(在Python的标准库中,这是Python的重要组成部分)。itertools
0赞 Talal Ghannam 5/4/2023
感谢 T. @Alain代码。它们很简单,效果很好。
0赞 Talal Ghannam 5/2/2023 #2

我只是想出答案......感谢斯科特·亨特的提示。

def decode(L, x):
        R = []
        
        if x > 0:
            for j in L:
                Long = L+L
                i1 = L.index(j)+1
                i2 = L.index(j)+x+1
                R.append(sum(Long[i1:i2]))
        
        elif x < 0:
            for j in L:
                x = np.abs(x)
                Long = L+L
                Long = Long[::-1]
                i1 = L.index(j)+1
                i2 = L.index(j)+x+1
                R.append(sum(Long[i1:i2]))
            R = R[::-1]   
                
        return R