在列表中交换两个子列表

时间:2015-06-29 08:41:04

标签: python list

给出以下列表:

my_list=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

我希望能够尽可能快速有效地将子列表my_list[2:4]与子列表my_list[7:10]交换,以获取新列表:

new_list=[0, 1, 7, 8, 9, 4, 5, 6, 2, 3, 10, 11, 12]

这是我的尝试:

def swap(s1, s2, l):

    seg1=l[:s1.start]+l[s2]
    seg2=l[s1.stop : s2.start]
    seg3=l[s1]+l[s2.stop:]

    return seg1+seg2+seg3


print swap(slice(2,4), slice(7,10), [0,1,2,3,4,5,6,7,8,9,10,11,12])

这会打印出所需的输出,虽然这样做对我来说很糟糕。

是否有更简单,更优雅的方式,不会为每个函数调用创建四个新列表? (我打算多打电话给这个功能)

我不介意(实际上我更喜欢)更改原始列表,而不是在每次函数调用时创建新实例。

6 个答案:

答案 0 :(得分:27)

可以分配切片。

可以使用realurl交换两个变量。

结合以上两个::

a, b = b, a

请注意 - 如果切片的大小不同 - 顺序很重要:如果以相反的顺序交换,最终会得到不同的结果,因为它会先改变初始值项目(较低的索引),然后是较高的索引项目(但第一次分配将在不同的位置移动)。

此外,切片不得重叠。

答案 1 :(得分:4)

您可以在此处使用常规交换技术(x,y = y,x),但仅当您按正确顺序执行交换时:x必须是第二个(最右侧)切片,而y是第一个(最左边)切片。

>>> my_list=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> my_list[7:10], my_list[2:4] = my_list[2:4], my_list[7:10]
>>> my_list
[0, 1, 7, 8, 9, 4, 5, 6, 2, 3, 10, 11, 12]

这是有效的,因为它会首先分配给my_list[7:10],然后分配给my_list[2:4]

如果以相反的顺序执行此操作,则首先分配到my_list[2:4]将更改右侧项目的位置,因为子列表具有不同的长度,这将产生不正确的结果。

在性能方面,这可能会或可能不会比您的代码更快:它可能取决于列表的长度和切片。您必须在典型的用例上进行测试才能看到。

答案 2 :(得分:2)

我认为最好使用连接和切片。如果您传递列表然后两个带有索引对的列表,那么您可以将列表分开并重新排列两个子列表。请注意,public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View grid = inflater.inflate(R.layout.grid_single, null); final String imgPath = imgList.get(position).toString(); if (convertView == null) { Bitmap bitmap = BitmapFactory.decodeFile(imgPath); if(bitmap != null) { ImageView img = (ImageView)grid.findViewById(R.id.grid_image); img.setImageBitmap(bitmap); ImageView bin = (ImageView)grid.findViewById(R.id.grid_delete_image); bin.setImageResource(deleteImage); bin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { imgList.remove(imgPath); File fs = new File(imgPath); Boolean fileDeleted = fs.delete(); if(fileDeleted) { notifyDataSetChanged(); } Toast.makeText(mContext, "Image Deleted:" + Integer.toString (position), Toast.LENGTH_SHORT).show(); } }); } } else { grid = (View) convertView; } return grid; } indexA都以常规切片的方式工作,包含起始编号,但最后一个不包含。

indexB

答案 3 :(得分:2)

不完全明显(或有效)但它有效。我很想知道是否可以进一步利用切片对象。

import itertools

def replace(s1, s2, l):
    lslice = [slice(0,s1.start), s2, slice(s1.stop, s2.start), s1, slice(s2.stop,len(l))]
    return list(itertools.chain.from_iterable([l[x] for x in lslice]))

答案 4 :(得分:1)

这是另一种方法:

import itertools
my_list=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
my_list2 = []
my_list2.extend((my_list[0:2],my_list[7:10],my_list[4:7],my_list[2:4],my_list[10:]))
new_list = list(itertools.chain.from_iterable(my_list2)

new_list打印输出:

[0, 1, 7, 8, 9, 4, 5, 6, 2, 3, 10, 11, 12]

答案 5 :(得分:0)

我认为使用列表索引作为参数要好得多。

如果您想重新定义替换功能,请执行以下操作:

my_list=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

def slice_replace(src_list, l_start, l_end, r_start, r_end):
    if l_end <= r_start:
        return src_list[:l_start] + src_list[r_start:r_end] + src_list[l_end:r_start] + src_list[l_start:l_end] + src_list[r_end:]
    else:
        return slice_replace(src_list, r_start, r_end, l_start, l_end)

print my_list
new_list = slice_replace(my_list, 2, 4, 7, 10)
print new_list

new_list = slice_replace(my_list, 7, 10, 2, 4)
print new_list

我修好了。