给出以下列表:
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])
这会打印出所需的输出,虽然这样做对我来说很糟糕。
是否有更简单,更优雅的方式,不会为每个函数调用创建四个新列表? (我打算多打电话给这个功能)
我不介意(实际上我更喜欢)更改原始列表,而不是在每次函数调用时创建新实例。
答案 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
我修好了。