2

I would like to move more than one item from one list to another.

list1 = ['2D','  ','  ','  ','  ','  ','  ','  ','  ']
list2 = ['XX','XX','5D','4S','3D','  ','  ','  ','  ']
list3 = ['XX','XX','XX','8C','7H','6C','  ','  ','  ']

In the code above ' ' is a double space

I would like to be able to move '5D','4S','3D' from list2 onto '8C','7H','6C' in list3.

I've tried the code below but it doesn't work.

list1 = ['2D','  ','  ','  ','  ','  ','  ','  ','  ']
list2 = ['XX','XX','5D','4S','3D','  ','  ','  ','  ']
list3 = ['XX','XX','XX','8C','7H','6C','  ','  ','  ']


items_to_be_moved = list2[list2.index('XX')+2 : list2.index('  ')]

list3[list3.index('  ')] = items_to_be_moved
del list2[list2.index('XX')+2 : list2.index('  ')]

print('list2',list2)
print('list3',list3)

and this returns

list2 ['XX', 'XX', '  ', '  ', '  ', '  ']
list3 ['XX', 'XX', 'XX', '8C', '7H', '6C', ['5D', '4S', '3D'], '  ', '  ']

However, i dont want to use list2.index('XX')+2, i would like to use a code that gives the last index of 'XX' just like list2.index(' ') gives the first index of ' '.

Also, i dont want the moved items to be in a separate list of their own within another list. For example: instead of returning

"list3 ['XX', 'XX', 'XX', '8C', '7H', '6C', ['5D', '4S', '3D'], '  ', '  ']"

the list

"list3 ['XX', 'XX', 'XX', '8C', '7H', '6C','5D', '4S', '3D', '  ', '  ']"

should be returned.

Reinstate Monica
  • 4,568
  • 1
  • 24
  • 35
Code Bisector
  • 67
  • 1
  • 4

6 Answers6

6

To replace the correct items, use slice assignment.

list1 = ['2D','  ','  ','  ','  ','  ','  ','  ','  ']
list2 = ['XX','XX','5D','4S','3D','  ','  ','  ','  ']
list3 = ['XX','XX','XX','8C','7H','6C','  ','  ','  ']

list3[3:6] = list2[2:5]

print list3
# ['XX', 'XX', 'XX', '5D', '4S', '3D', '  ', '  ', '  ']

If you want to start from after the final consecutive 'XX', you can use:

from itertools import takewhile
i = sum(1 for _ in takewhile(lambda elem: elem == 'XX', list3))

list3[i:i+3] = list2[i-1:i+2]

to find the index of the last one.

agf
  • 171,228
  • 44
  • 289
  • 238
2

well if all of the 'xx' are always before the needed there is another way (beside the one suggested by @turek) using 'list.count('xx')' and the slicing :

list[count-1:count+2]

you can use the slice operator to do the insert also I would probably iterate like suggested by @intra-c

alonisser
  • 11,542
  • 21
  • 85
  • 139
1

First, here's how to find the last index. But beware, if you get the index number of the last copy of XX, what if the list reads, e.g., ['XX', '1D', 'XX', '4S'] so that there's a valid item in the middle?

Anyway, once you have a span that you want to move from one list to another, you need only use the slice operator to do the insert and delete:

>>> list2[2:5]
['5D', '4S', '3D']
>>> list3[6:6] = list2[2:5]
>>> list3
['XX', 'XX', 'XX', '8C', '7H', '6C', '5D', '4S', '3D', '  ', '  ', '  ']

You can use del to remove from list2, or you can just assign to the slice:

>>> list2[2:5] = []
>>> list2
['XX', 'XX', '  ', '  ', '  ', '  ']
Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • Doing the slice assignment right over the old values is fast because you don't have to resize the list and move values. Your method makes you move all the values after that point in the list twice. The linked method of finding the last index also requires you to make a copy of the list, and iterate over the whole list, which isn't necessary. – agf Mar 19 '12 at 21:46
  • It sounded like he wanted the new (output) list to be bigger, not overwritten. It's a little confusing because his sample input `list3` has ten items and his sample output has 11, which does not match either a pure-insert or a pure-overwrite. (I'm surprised the step-by-negative-one slice method is not special cased inside Python. Still, as I noted, there's the danger of taking things that are not-XX but are surrounded by the XX markers. Your `takewhile` is the obvious right way to get contiguous XX items, especially since `itertools` are generally very fast.) – torek Mar 20 '12 at 00:00
  • Gah, I went back and re-read the inputs, outputs, and problem, and I'm entirely wrong, he did say "overwrite". – torek Mar 20 '12 at 00:02
0

Try looping through with

for item in items_to_be_moved:
    # Add items one at a time
Intra
  • 2,089
  • 3
  • 19
  • 23
0

On the second topic:

Don't think there's a function for finding last occurance in lists, but you could either do a loop

pos = 0
while 1:
    try:
        pos = list3.index('XX',pos+1)
    except ValueError:
        break
if pos == 0 and list3[0] != 'XX':
    #Do something to pos if there was no XX in list...

or reverse the list in-place do the index-thing reverse it back and recalc the position.

list3.reverse()
pos = list3.index('XX')
list3.reverse()
pos = len(list3) - pos - 1
deinonychusaur
  • 7,094
  • 3
  • 30
  • 44
0

Don't forget about negative indices for slicing from the end:

i2_begin = -list2[::-1].index('XX')
i2_end = list2.index('  ')
i3 = list3.index('  ')

list3[i3:i3] = list2[i2_begin:i2_end]
del list2[i2_begin:i2_end]
Reinstate Monica
  • 4,568
  • 1
  • 24
  • 35