使用* args和指定的列表索引

时间:2018-01-24 08:33:14

标签: python list function indexing

我之前在Stack Overflow上发布了一个问题,询问如何组合由整数值组成的列表,同时还对各个索引(Summing lists of different lengths in Python beginning at a specified index using a function)处的值求和。我从@pault得到了一个很好的答案,但现在我想知道我是否可以在函数中使用*args来添加任意数量的列表。

例如,我可以有4个列表(或任何数量):

a = [0, 1, 2, 3, 4, 5, 6, 7]
b = [2, 4, 6, 8, 10, 12]
c = [1, 1, 1, 1, 1]
d = [2, 2, 2, 2, 2]

我想将列表bcd插入a中的指定索引中。我可以说,在b插入列表a[2],在c插入a[2],在d插入a[5]。结果将是[0 1 5 8 11 16 19 21]

这是我目前使用的代码(归功于@pault):

a = [0, 0, 0, 0, 0, 0, 0, 0, 0]
b = [1, 1, 1, 1, 1, 1, 1, 1, 1]
c = [5, 2]

def combine(lista, listb, index_in_list_a_to_start_insert):

    newb = [0]*index_in_list_a_to_start_insert + listb
    max_len = max(len(lista), len(newb))
    newa = lista if len(lista) >= max_len else lista + [0]*(max_len-len(lista))
    newb = newb if len(newb) >= max_len else newb + [0]*(max_len-len(newb))

    return [a + b for a, b in zip(newa,newb)][0:len(a)]

主要观点是在a任意索引处添加任意数量的列表,同时保持a的长度相同,例如,如果我在{{{{}}添加了列表b 1}},结果为a[6]。我认为我最大的问题是将列表与我想要插入的索引相关联,例如让列表[0, 1, 2, 3, 4, 5, 8, 11]进入b并指定列表a[3]进入{{ 1}}等,同时保持列表c的长度相同,那么可能必须与a[4]进行一些配对?像a这样的东西?我真的不知道怎么回事。我使用的是Python 3.4.3。

2 个答案:

答案 0 :(得分:0)

我按照要求制作了这个功能。但是我没有使用*args,因为我只是认为它会使代码在这个用例中不那么清晰。在这里,我们有明确的命名,代码似乎做你所要求的。

def combine(refList, listsToAdd, indexes):
    lenRef = len(refList)

    #   Navigating through lists you want to add.
    for listToAdd, startIndex in zip(listsToAdd, indexes):
        #   We'll need a break point later.
        lenToAdd = len(listToAdd)

        #   Setting index of the list to add numbers from.
        count = 0

        #   Going from the start index, until the end of our original list.
        for refIdx in range(startIndex, lenRef):
            #   If we reach the end of our toAdd list... break.
            if count >= lenToAdd:
                break
            refList[refIdx] += listToAdd[count]
            count += 1

    return refList

if __name__ == '__main__':
    a = [0, 1, 2, 3, 4, 5, 6, 7]
    b = [2, 4, 6, 8, 10, 12]
    c = [1, 1, 1, 1, 1]
    d = [2, 2, 2, 2, 2]

    newList = combine(a, listsToAdd=[b, c, d], indexes=[2, 2, 5])
    print newList
    # outputs : [0, 1, 5, 8, 11, 16, 19, 21]

答案 1 :(得分:0)

如果我正确理解您的问题,您实际需要做的是将listb放入列表列表中。

要对combine进行最少量的更改,请使用zip遍历listb和每个索引的每个项目,这两个项目现在都应该是列表列表:

def combine(lista, listb, index_in_list_a_to_start_insert):
    if isinstance(listb[0], list):  # check if the first item in listb
                                    # is a list; check for empty lists
        for actual_list_b, actual_insert_index in zip(listb, index_in_list_a_to_start_insert):
            lista = combine(lista, actual_list_b, actual_insert_index)
        return lista

    newb = [0]*index_in_list_a_to_start_insert + listb
    max_len = max(len(lista), len(newb))
    newa = lista if len(lista) >= max_len else lista + [0]*(max_len-len(lista))
    newb = newb if len(newb) >= max_len else newb + [0]*(max_len-len(newb))

    return [a + b for a, b in zip(newa,newb)][0:len(a)]

使用上面的示例列表:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> b = [2, 4, 6, 8, 10, 12]
>>> c = [1, 1, 1, 1, 1]
>>> d = [2, 2, 2, 2, 2]
>>>
>>> combine(a, [b, c], [3, 4])
[0, 1, 2, 5, 9, 12, 15, 18]
>>>

您需要为listb和索引列表添加更多isinstance()检查,以确保两者都是列表,或者两者都不是列表,并且两者都具有相同的长度,最短的一个确定{的结果{1}}。