首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按索引拆分列表

按索引拆分列表
EN

Code Review用户
提问于 2014-04-22 11:15:12
回答 3查看 75.7K关注 0票数 15

我试图构建一个有效的函数,将任意大小的列表按给定的索引数分割。这个方法很有效,我花了几个小时才把它做好(我讨厌在使用索引时出错是多么容易)。

我是不是想太多了?你能帮我把代码最小化吗?我只是没看到而已。另外,是否有任何方法可以简化如此多变量的输入,例如在这种情况下?

代码语言:javascript
复制
def lindexsplit(List,*lindex):

    index = list(lindex)

    index.sort()

    templist1 = []
    templist2 = []
    templist3 = []

    breakcounter = 0
    itemcounter = 0
    finalcounter = 0


    numberofbreaks = len(index)
    totalitems = len(List)

    lastindexval = index[(len(index)-1)]
    finalcounttrigger = (totalitems-(lastindexval+1))

    for item in List:

        itemcounter += 1

        indexofitem = itemcounter - 1

        nextbreakindex = index[breakcounter]

        #Less than the last cut
        if breakcounter <= numberofbreaks:

            if indexofitem < nextbreakindex:

                templist1.append(item)

            elif breakcounter < (numberofbreaks - 1):

                templist1.append(item)

                templist2.append(templist1)

                templist1 = []

                breakcounter +=1

            else:

                if indexofitem <= lastindexval and indexofitem <= totalitems:

                    templist1.append(item)

                    templist2.append(templist1)

                    templist1 = []

                else:

                    if indexofitem >= lastindexval and indexofitem < totalitems + 1:

                        finalcounter += 1

                        templist3.append(item)

                        if finalcounter == finalcounttrigger:

                            templist2.append(templist3)


    return templist2

示例:

代码语言:javascript
复制
mylist = [1,2,3,4,5,6,7,8,9,0,10,11,12,13,14,15]
lindexsplit(mylist,3,5,8)
return [[1, 2, 3, 4], [5, 6], [7, 8, 9], [0, 10, 11, 12, 13, 14, 15]]
EN

回答 3

Code Review用户

发布于 2014-04-22 13:09:08

有更简单的方法来做到这一点。您可以使用列表切片zip函数。

列表切片本质上是将给定的列表分成几个部分。一般形式是list[start:stop:step]。切片的start部分指定要包含在切片中的列表的第一个索引。stop部分指定我们希望在切片中排除的列表的第一个索引。step一节定义了我们移动的指数,以及向哪个方向移动(基于它是正的还是负的)。举个例子:

代码语言:javascript
复制
>>> x = [1, 2, 3, 4]
>>> x[1:3]
[2, 3]
>>> x[2:]
[3, 4]
>>> x[0:4]
[1, 2, 3, 4]
>>> x[0:4:1]
[1, 2, 3, 4]
>>> x[0:4:2]
[1, 3]
>>> x[0:4:3]
[1, 4]
>>> x[0:4:4]
[1]
>>> x[0:4:5]
[1]

zip函数接受序列并创建一个zip对象,其中包含相应的索引元素的元组:

代码语言:javascript
复制
>>> for pair in zip([1, 2, 3], ['a', 'b', 'c']):
...    print(pair)
(1, 'a')
(2, 'b')
(3, 'c')

您可以结合这两种策略来简化您的功能。下面是您的lindexsplit函数的版本:

代码语言:javascript
复制
def lindexsplit(some_list, *args):
    # Checks to see if any extra arguments were passed. If so,
    # prepend the 0th index and append the final index of the 
    # passed list. This saves from having to check for the beginning
    # and end of args in the for-loop. Also, increment each value in 
    # args to get the desired behavior.
    if args:
        args = (0,) + tuple(data+1 for data in args) + (len(some_list)+1,)

    # For a little more brevity, here is the list comprehension of the following
    # statements:
    #    return [some_list[start:end] for start, end in zip(args, args[1:])]
    my_list = []
    for start, end in zip(args, args[1:]):
        my_list.append(some_list[start:end])
    return my_list
票数 16
EN

Code Review用户

发布于 2014-04-22 13:02:12

为了使您的代码更加美观/节能型,需要做一些修饰性的更改:

固定格式

  • 删除一些换行符,因为这会使代码更难阅读。
  • 更改变量名以跟随PEP 8
  • 您的代码缺乏文档,因此很难理解。

使用枚举

枚举完全实现了您想要实现的目标:在可迭代的循环中跟踪索引。只需使用for indexofitem,item in enumerate(List):

删除嵌套逻辑

的级别

使用elif,您可以使代码更容易理解。for-loop的内部变成:

代码语言:javascript
复制
    if breakcounter <= numberofbreaks:
        if indexofitem < nextbreakindex:
            templist1.append(item)
        elif breakcounter < (numberofbreaks - 1):
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
            breakcounter +=1
        elif indexofitem <= lastindexval and indexofitem <= totalitems:
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
        elif indexofitem >= lastindexval and indexofitem < totalitems + 1:
            finalcounter += 1
            templist3.append(item)
            if finalcounter == finalcounttrigger:
                templist2.append(templist3)

重写您的比较

在Python中,您可以用非常自然的方式编写比较:indexofitem >= lastindexval and indexofitem < totalitems + 1变成lastindexval <= indexofitem < totalitems + 1

使用智能索引获取数组

的最后一个元素

您可以用更清晰的lastindexval = index[(len(index)-1)]重写lastindexval = index[-1]

重新思考您的逻辑

totalitems = len(List)indexofitem0len(List) - 1 (包括在内)。因此,indexofitem <= totalitems并不是一个值得检查的有趣条件。indexofitem < totalitems + 1也是如此。

一旦这一项被删除,我们就有:

代码语言:javascript
复制
    #Less than the last cut
    if breakcounter <= numberofbreaks:
        if indexofitem < nextbreakindex:
            templist1.append(item)
        elif breakcounter < (numberofbreaks - 1):
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
            breakcounter +=1
        elif indexofitem <= lastindexval:
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
        elif lastindexval <= indexofitem:
            finalcounter += 1
            templist3.append(item)
            if finalcounter == finalcounttrigger:
                templist2.append(templist3)

-重新思考您的逻辑(之二)

在上面的代码中,最后两个elif检查有点多余:如果我们不进入indexofitem <= lastindexval块,那么必须有lastindexval < indexofitem和lastindexval <=索引。

清理完后,代码如下所示:

代码语言:javascript
复制
    for indexofitem,item in enumerate(List):
        nextbreakindex = index[breakcounter]

        #Less than the last cut
        if breakcounter <= numberofbreaks:
            if indexofitem < nextbreakindex:
                templist1.append(item)
            elif breakcounter < (numberofbreaks - 1):
                templist1.append(item)
                templist2.append(templist1)
                templist1 = []
                breakcounter +=1
            elif indexofitem <= lastindexval:
                templist1.append(item)
                templist2.append(templist1)
                templist1 = []
            else:
                finalcounter += 1
                templist3.append(item)
                if finalcounter == finalcounttrigger:
                    templist2.append(templist3)
    return templist2

-重新思考您的逻辑(ter)

如果不更改breakcounter > numberofbreaks作为breakcounternumberofbreaks,则循环中不会发生任何事情。如果真的是这样的话,我们最好还是跳出循环。然而,事情甚至比这更好:我们再次处于一种不可能发生的情况。这可以通过两种不同的方式来看待:

  • 如果breakcounternumberofbreaks大,nextbreakindex = index[breakcounter]就会抛出一个异常。
  • breakcounter一次只能增加一个元素。只有在breakcounter < (numberofbreaks - 1)时才会发生这种情况。因此,一旦breakcounter到达numberofbreaks - 1,它就停止生长。

在重写结束时,您的代码如下所示:

代码语言:javascript
复制
def lindexsplit(List,*lindex):
    index = list(lindex)
    index.sort()

    templist1 = []
    templist2 = []
    templist3 = []

    breakcounter = 0
    finalcounter = 0

    numberofbreaks = len(index)

    lastindexval = index[-1]
    finalcounttrigger = (len(List)-(lastindexval+1))

    for indexofitem,item in enumerate(List):
        nextbreakindex = index[breakcounter]

        if indexofitem < nextbreakindex:
            print "A"
            templist1.append(item)
        elif breakcounter < (numberofbreaks - 1):
            print "B"
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
            breakcounter +=1
        elif indexofitem <= lastindexval:
            print "C"
            templist1.append(item)
            templist2.append(templist1)
            templist1 = []
        else:
            print "D"
            finalcounter += 1
            templist3.append(item)
            if finalcounter == finalcounttrigger:
                templist2.append(templist3)
    return templist2

我认为还有很多需要改进的地方,可以编写一个更简单的解决方案(如评论中所建议的)。

票数 5
EN

Code Review用户

发布于 2020-01-22 06:45:16

在下面提到seq。下面提到的代码没有像预期的那样工作:

代码:

代码语言:javascript
复制
def lindexsplit(some_list, *args):
    # Checks to see if any extra arguments were passed. If so,
    # prepend the 0th index and append the final index of the
    # passed list. This saves from having to check for the beginning
    # and end of args in the for-loop. Also, increment each value in
    # args to get the desired behavior.
    if args:
        args = (0,) + tuple(data+1 for data in args) + (len(some_list)+1,)

    # For a little more brevity, here is the list comprehension of the following
    # statements:
    #    return [some_list[start:end] for start, end in zip(args, args[1:])]
    my_list = []
    for start, end in zip(args, args[1:]):
        my_list.append(some_list[start:end])
    return my_list

l = [1,2,3,4,5,6,7,8,9,0,11,12,13,14,15]
print(lindexsplit(l, 4,7,9,11))

投入1:

代码语言:javascript
复制
print(lindexsplit(l, 4,7,9,11))

产出1:

代码语言:javascript
复制
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 0], [11, 12], [13, 14, 15]]

投入2:

代码语言:javascript
复制
print(lindexsplit(l, 4,7,9,15))

产出2:

代码语言:javascript
复制
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 0], [11, 12, 13, 14, 15], []]

请看一个简单的和更新的功能,它适用于所有的情况,如果它失败的地方,那么请告诉我。

代码:

代码语言:javascript
复制
def lindexsplit(List, lindex):
    index_list = lindex
    index_list.sort()

    new_list = []

    print(index_list)

    len_index = len(index_list)
    for idx_index, index in enumerate(index_list):
        if len(index_list) == 1:
            new_list = [List[:index+1], List[index+1:]]
        else:
            if idx_index==0:
                new_list.append(List[:index+1])
                # print('Start', List[:index+1])
            elif idx_index==len_index-1:
                new_list.append(List[index_list[idx_index - 1] + 1:index + 1])
                # print('End', List[index_list[idx_index - 1] + 1:index + 1])
                if List[index+1:]:
                    new_list.append(List[index+1:])
                    # print('End', List[index+1:])
            else:
                new_list.append(List[index_list[idx_index-1]+1:index+1])
                # print('Between', List[index_list[idx_index-1]+1:index+1])

    return new_list


l = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
l = [str(ele) for ele in l]
print(lindexsplit(l, [0,1, 8, 14, 15] ))

投入1:

代码语言:javascript
复制
print(lindexsplit(l, 4,7,9,11))

产出1:

代码语言:javascript
复制
[['0', '1', '2', '3', '4'], ['5', '6', '7'], ['8', '9'], ['10', '11'], ['12', '13', '14', '15']]

投入2:

代码语言:javascript
复制
print(lindexsplit(l, 4,7,9,15))

产出2:

代码语言:javascript
复制
[['0', '1', '2', '3', '4'], ['5', '6', '7'], ['8', '9'], ['10', '11', '12', '13', '14', '15']]

投入3:

代码语言:javascript
复制
print(lindexsplit(l, 4,7,9,15))

产出3:

代码语言:javascript
复制
[['0'], ['1'], ['2', '3', '4', '5', '6', '7', '8'], ['9', '10', '11', '12', '13', '14'], ['15']]
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/47868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档