Move an Item Inside a List

Move an item inside a list?

Use the insert method of a list:

l = list(...)
l.insert(index, item)

Alternatively, you can use a slice notation:

l[index:index] = [item]

If you want to move an item that's already in the list to the specified position, you would have to delete it and insert it at the new position:

l.insert(newindex, l.pop(oldindex))

Move an element in a list

You mean, like, changing C and the dot position? You could have something like:

list_ = [A, B, C, ., D]
list_[2], list_[3] = list_[3], list_[2]

The list_ would look like [A, B, ., C, D].

How to move an Item inside a list of lists?

A list of lists is clunky for representing a matrix. Instead you can use an actual matrix-like type, the NumPy ndarray. NumPy includes a roll() function that can be used to translate a shape, so you just need to supply the directions.

Firstly, I'll use 0 and 1 for better readability.

import numpy as np

space = np.array([
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
])

Then we can roll it right:

>>> np.roll(space, 1, 1)
[[0 0 1 1]
[0 0 1 0]
[0 0 1 0]
[0 0 0 0]]

To do other directions, you just need to supply the right values, and you can wrap that up in a function like this:

def move_shape_in_array(array, direction):
directions = {
"up": (-1, 0),
"left": (-1, 1),
"down": (1, 0),
"right": (1, 1),
}
shift, axis = directions[direction]
return np.roll(array, shift=shift, axis=axis)
>>> move_shape_in_array(space, "right")
[[0 0 1 1]
[0 0 1 0]
[0 0 1 0]
[0 0 0 0]]

But this doesn't guard against the shape going off the edge. Instead it wraps around:

>>> move_shape_in_array(space, "up")
[[0 1 0 0]
[0 1 0 0]
[0 0 0 0]
[0 1 1 0]]

To actually guard against it, check if there are any 1s on the edge before moving:

edge_idx = 0 if shift == -1 else -1
edge = array[edge_idx] if axis == 0 else array[:, edge_idx]

if edge.any():
return array

(Insert this between the shift, axis = and return lines in the function above.)

Move items in list from front to the back

Use slicing of list:

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> idx = a.index(7)
>>> a = a[idx:] + a[:idx]
>>> a
[7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]

Note that this will throw a ValueError if the value being searched is not found in the array, in which case you will need to capture it using try-except block

Moving a sublist of items in a list to a new position

Consider I the item to move, J the next adjacent item and N your target idx

Two cases:

  • case 1: item is before N
    I|J| | | |N
J| | | |N|I

All your elements between I+1 and N (included) are translated to the left

  • case 2: item is after N
    N| | | |I|J
N|I| | | |J

All the elements between N+1 and I-1 are translated to the right.

At this point an approximate pseudocode (about the indices) looks like:

while el = L.pop()
moveItem(el, N)
if el < N
for all indices of L > el and el < N
indices--
else
for all indices of L < el and > N
indices++
N+=1 #target our last elem

Below a (supposed) proper implem


def move_item(lst, src, dst):
print('move ', src, dst)
el = lst.pop(src)
lst.insert(dst, el)

def move_items(arr, indices, N):
while(len(indices)):
el = indices.pop(0)
if el == N:
#our elem is in place
#target is the elem after
N += 1
continue

if el < N:
#pop effect
N -=1

#insert the elem after N (
move_item(arr, el, N)
for j in range(len(indices)):
el2 = indices[j]
if el2 > el and el2 <= N:
indices[j] -= 1
else:
move_item(arr, el, N)
for j in range(len(indices)):
el2 = indices[j]
if el2 > N and el2 < el:
indices[j] += 1

#we have inserted an elem after N
#next target is our last elem
N += 1
print('now', arr, 'indices', indices)

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

Generic List - moving an item within the list

I know you said "generic list" but you didn't specify that you needed to use the List(T) class so here is a shot at something different.

The ObservableCollection(T) class has a Move method that does exactly what you want.

public void Move(int oldIndex, int newIndex)

Underneath it is basically implemented like this.

T item = base[oldIndex];
base.RemoveItem(oldIndex);
base.InsertItem(newIndex, item);

So as you can see the swap method that others have suggested is essentially what the ObservableCollection does in it's own Move method.

UPDATE 2015-12-30: You can see the source code for the Move and MoveItem methods in corefx now for yourself without using Reflector/ILSpy since .NET is open source.

Move Item to front of list when using for in loop

Modifying a list while iterating over it, is generally not recommended, that said:

>>> ctr = 0
>>> lst = [1,2,3,4,5,6]
>>> for i in lst:
...: if ctr == 3:
...: lst.insert(0,lst.pop(ctr))
...: break
...: ctr += 1
...:
>>> lst
[4, 1, 2, 3, 5, 6]

Or,

>>> lst = [1,2,3,4,5,6]
>>> for i,x in enumerate(lst):
... if x == 3:
... lst.insert(0,lst.pop(i))
... break
>>> lst
[3, 1, 2, 4, 5, 6]


Related Topics



Leave a reply



Submit