我试图构建一个有效的函数,将任意大小的列表按给定的索引数分割。这个方法很有效,我花了几个小时才把它做好(我讨厌在使用索引时出错是多么容易)。
我是不是想太多了?你能帮我把代码最小化吗?我只是没看到而已。另外,是否有任何方法可以简化如此多变量的输入,例如在这种情况下?
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示例:
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]]发布于 2014-04-22 13:09:08
有更简单的方法来做到这一点。您可以使用列表切片和zip函数。
列表切片本质上是将给定的列表分成几个部分。一般形式是list[start:stop:step]。切片的start部分指定要包含在切片中的列表的第一个索引。stop部分指定我们希望在切片中排除的列表的第一个索引。step一节定义了我们移动的指数,以及向哪个方向移动(基于它是正的还是负的)。举个例子:
>>> 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对象,其中包含相应的索引元素的元组:
>>> for pair in zip([1, 2, 3], ['a', 'b', 'c']):
... print(pair)
(1, 'a')
(2, 'b')
(3, 'c')您可以结合这两种策略来简化您的功能。下面是您的lindexsplit函数的版本:
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发布于 2014-04-22 13:02:12
为了使您的代码更加美观/节能型,需要做一些修饰性的更改:
枚举完全实现了您想要实现的目标:在可迭代的循环中跟踪索引。只需使用for indexofitem,item in enumerate(List):。
的级别
使用elif,您可以使代码更容易理解。for-loop的内部变成:
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)和indexofitem从0到len(List) - 1 (包括在内)。因此,indexofitem <= totalitems并不是一个值得检查的有趣条件。indexofitem < totalitems + 1也是如此。
一旦这一项被删除,我们就有:
#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 <=索引。
清理完后,代码如下所示:
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如果不更改breakcounter > numberofbreaks作为breakcounter和numberofbreaks,则循环中不会发生任何事情。如果真的是这样的话,我们最好还是跳出循环。然而,事情甚至比这更好:我们再次处于一种不可能发生的情况。这可以通过两种不同的方式来看待:
breakcounter比numberofbreaks大,nextbreakindex = index[breakcounter]就会抛出一个异常。breakcounter一次只能增加一个元素。只有在breakcounter < (numberofbreaks - 1)时才会发生这种情况。因此,一旦breakcounter到达numberofbreaks - 1,它就停止生长。在重写结束时,您的代码如下所示:
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我认为还有很多需要改进的地方,可以编写一个更简单的解决方案(如评论中所建议的)。
发布于 2020-01-22 06:45:16
在下面提到seq。下面提到的代码没有像预期的那样工作:
代码:
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:
print(lindexsplit(l, 4,7,9,11))产出1:
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 0], [11, 12], [13, 14, 15]]投入2:
print(lindexsplit(l, 4,7,9,15))产出2:
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 0], [11, 12, 13, 14, 15], []]请看一个简单的和更新的功能,它适用于所有的情况,如果它失败的地方,那么请告诉我。
代码:
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:
print(lindexsplit(l, 4,7,9,11))产出1:
[['0', '1', '2', '3', '4'], ['5', '6', '7'], ['8', '9'], ['10', '11'], ['12', '13', '14', '15']]投入2:
print(lindexsplit(l, 4,7,9,15))产出2:
[['0', '1', '2', '3', '4'], ['5', '6', '7'], ['8', '9'], ['10', '11', '12', '13', '14', '15']]投入3:
print(lindexsplit(l, 4,7,9,15))产出3:
[['0'], ['1'], ['2', '3', '4', '5', '6', '7', '8'], ['9', '10', '11', '12', '13', '14'], ['15']]https://codereview.stackexchange.com/questions/47868
复制相似问题