简体   繁体   English

用函数[python 3]替换列表中的两个元素

[英]Replacing two elements of a list in place with a function [python 3]

I want to create a function such that when I enter a list and parameters, it will replace two items of the list with each other. 我想创建一个函数,这样当我输入列表和参数时,它将相互替换列表中的两个项目。 This code needs to be in place. 该代码必须到位。

The code needs to start like so: 代码需要像这样开始:

def reverse_sublist(lst,start,end): 
...

An example of what it's supposed to do: 应该做的一个例子:

>>> lst = [1, 2, 3, 4, 5]
>>> reverse_sublist (lst,0,4)
>>> lst
[4, 3, 2, 1, 5]

I tried to write some pseudo code of how to do it: 我试图写一些伪代码来做到这一点:

start=i, end=n #1#
make a copy of both lst[i], lst[n] inside list, right next to the original #2#
do lst[i]=lst[n+1] and lst[n]=lst[i+1] 
delete lst[i+1], lst[n+1]

I just began learning python so I have several questions: 我刚开始学习python,所以我有几个问题:

How can I define the parameters of the function (#1#) ? 如何定义函数(#1#)的参数?

How can I do these operations (#2#) on the list with the function ? 如何使用功能在列表上进行这些操作(#2#)?

Thanks in advance. 提前致谢。

I think what you want is: 我认为您想要的是:

def reverse_sublist(lst, start, end):
    lst[start:end] = reversed(lst[start:end])

Note the definition of the three arguments to the function on the first line, in parentheses after the name of the function. 请注意,在函数名称后面的括号中,第一行中函数的三个参数的定义。

Your current pseudocode appears to be for swapping the items at start and end , which is not what your example shows. 您当前的伪代码似乎是用于在startend 交换项目的,这不是您的示例所显示的。 If you did want to do this, you could do: 如果您确实想这样做,则可以执行以下操作:

def swap_items(lst, index1, index2):
    lst[index1], lst[index2] = lst[index2], lst[index1]

An additional note on your first approach: if you add extra items into the list you will throw off the indexing for the rest of the list. 关于第一种方法的附加说明:如果将更多项目添加到列表中,则将其余列表的索引删除。 For example, try this test implementation of your pseudocode: 例如,尝试以下测试实现的伪代码:

def test(lst, start, end):
    lst.insert(start+1, lst[start])
    lst.insert(end+1, lst[end])
    print(lst)
    lst[start] = lst[end+1]
    lst[end] = lst[start+1]
    print(lst)
    del lst[start+1]
    del lst[end+1]
    print(lst)

The result this gives is not the [5, 2, 3, 4, 1] you are expecting: 这给出的结果不是您期望的[5,2,3,4,1 [5, 2, 3, 4, 1]

>>> test([1, 2, 3, 4, 5], 0, 4)
[1, 1, 2, 3, 4, 4, 5] # after insert
[4, 1, 2, 3, 1, 4, 5] # after swap
[4, 2, 3, 1, 4] # after del

Instead, you would have to do the insert and swap on end+2 and end+1 to account for the extra item from the insert at start+1 : 取而代之的是,您必须在end+2end+1进行insert和交换,以解决start+1insert中的额外项:

def test(lst, start, end):
    lst.insert(start+1, lst[start])
    lst.insert(end+2, lst[end+1])
    lst[start], lst[end+1] = lst[end+2], lst[start+1]
    del lst[start+1]
    del lst[end+1]

I wanted to answer this with slices, but there's an edgecase that makes slices less elegant than @jonsharpe's answer, since when reverse slicing, you can't slice up to less than zero while reverse stepping, and the only way to accomplish it is to leave out the terminal element (please correct me if there's a more unified way of doing this): 我想用切片来回答这个问题,但是有一个边缘情况使切片不如@jonsharpe的回答那么优雅,因为当进行反向切片时,您不能在反向步进时将切片切到小于零,而唯一的方法是省略终端元素(如果有更统一的方法,请纠正我):

def reverse_sublist(lst, i, j):
    if i == 0: 
        lst[i:j] = lst[j-1::-1]
    else:
        lst[i:j] = lst[j-1:i-1:-1]

lst = [1, 2, 3, 4, 5]
reverse_sublist(lst,0,4)

and lst now returns: 现在lst返回:

[4, 3, 2, 1, 5]

As Jon suggested, this can be further simplified, and I'll break the slice notation out for ease of understanding: 正如乔恩(Jon)所建议的那样,这可以进一步简化,为了便于理解,我将对切片符号进行分解:

def reverse_sublist(lst, i, j):
    lst[i:j] = lst[j-1 :                # inclusive slice starting point
                   i-1 if i else None : # exclusive slice end point
                   -1]                  # step by negative one, i.e. reverse 

And then: 接着:

>>> lst = [1, 2, 3, 4, 5]
reverse_sublist(lst,0,4)
>>> 
>>> lst
[4, 3, 2, 1, 5]

I would still consider this less elegant than Jon's, because it's harder to read and more complex. 我仍然认为它不如乔恩的优雅,因为它更难阅读且更复杂。 Also, Jon's will work for negative indexes, this has problems with that. 而且,乔恩(Jon's)将适用于负索引,这有问题。

I think this accomplished what you want, your startlist (slist, the indices of where you start and finish the reversing are the parameters 我认为这完成了您想要的目标,起始列表(列表,开始和结束反转的位置的索引是参数

def reverse(slist,start,stop):
     temp = slist[start:stop]

temp is a sublist of the original list, reverse it in place temp是原始列表的子列表,将其反转

     temp.reverse()

you need to get the portion to the left (index < start) to have that available to prepend to your new list 您需要将左侧的部分(索引<开始)添加到新列表的前面

     originalLeft = slist[0:start]
     originalLeft.extend(temp)

You also need the segment from stop to the end of your original sublist 您还需要从停止到原始子列表末尾的段

     originalRight = slist[stop:]
     originalLeft.extend(originalRight)
     return originalLeft

>>> myList = [1,2,3,4,5,6,7,8,9,10,11,12,13]
>>> reverse(myList,4,9)
[1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13]
>>> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM