Solved

# Need some help with list manipulation in a Loop

Posted on 2015-01-18
162 Views
I have a simple loop that manipulates a list.
My code below simply looks for nr 1 and any 0's that are present.
All the 0's are put in a new list and the index containing 1 is changed to 0.
From the zerolist I then randomly change a 0 to 1.

I need to alter my code below a little so it does this:
Finds element/nr 1 then look for where 0 elements are and move my nr/element 1 to next available 0 .
Simply put: I need to move my nr to the next available 0.
If nr 1 is last in list [2,0,0,2,1] then the first index containing the 0 should be changed to 1 [2,1,0,2,0]

The list will always consist of 5 elements just like in the example below.
List will maximum contain one nr 1.

``````examplelist = [0,2,1,0,0]
zerolist = []
for i, j in enumerate(examplelist):
if j == 0:
zerolist.append(i)
elif j == 1:
examplelist[i]=0
shuffle(zerolist)
if zerolist:
examplelist[zerolist[0]]=1
``````

Any help would be appreciated !
0
Question by:Smyken
• 6
• 4
• 3

LVL 16

Expert Comment

ID: 40557496
I'm not 100% sure I understood the question,  but I'll give it a shot:

To get a list of indices where a 0 value is located:
``````zeropos = [ idx for idx, val in enumerate(examplelist) if val == 0
# result is [0, 3, 4]
``````

If you know that  a list contains a certain element, then you can find it's position with index()
example:
``````examplelist = [0,2,1,0,0]
examplelist.index(1)
>>> 2
``````

so to set the value to 0:
``````examplelist[examplelist.index(1)] = 0
``````

having the list zeropos and using the module random you can now randomly set one of these positions to 1:

``````import random
# get a random choize out of the positions containing zero
pos_to_change = random.choice(zerpos)

# now set this value to 1
examplelist[pos_to_change] = 1
``````

Complete solution (if I understood well):
``````import random

def find_one_and_move_to_a_zero(alist):
""" function moving a 1 value to a random zero value of the list """
# find 1 position
one_pos = alist.index(1)

# find 0 positions
zero_pos_lst = [ idx for idx, val in enumerate(alist) if val == 0 ]

# clear 1
alist[one_pos] = 0

# determine random 0 entry
chosen_zero_pos = random.choice(zero_pos_lst)

# set one value
alist[chosen_zero_pos] = 1

example_list =  [2,0,0,2,1]
print("Before %r" % example_list)
find_one_and_move_to_a_zero(example_list)
print("After %r" % example_list)
``````

Attention. The given solution will change the list. If you want to keep the original list unmodified, then this is also possible with two minor modifications. the function has to create a copy of the initial list and return it as result. If this is required I can show you
0

LVL 16

Expert Comment

ID: 40557531
Oops I accidentally just rewrote your initial code. So if you want to move the 1 to the first available 0 position, then use following function:

``````#!/usr/bin/env python

import random

def find_one_and_move_to_a_zero(alist):
""" function moving a 1 value to a randmo zero value of the list """
# find 1 position. No error checking. There MUST be a 1 in alist
one_pos = alist.index(1)

# set 1 to 0  # move next line to end of function if you want to move
# the 1 to the next 0 if the one was on a position left of the first 0
alist[one_pos] = 0

# find first 0 position.
zero_pos = alist.index(0)
alist[zero_pos] = 1

example_list =  [2,0,0,2,1]
print("Before %r" % example_list)
find_one_and_move_to_a_zero(example_list)
print("After %r" % example_list)
``````
0

LVL 45

Expert Comment

ID: 40557879
@Smyken

Will you need to repeat this process to move multiple 1 values to multiple zero values?
0

LVL 16

Expert Comment

ID: 40558090
The way I wrote the code it will only handle the first 1 it finds. This is what you asked for.
If you need something else, then try to give me a good example.
It should not be difficult to code it, but I'd like to be sure that the code will do exactly what you want.
0

LVL 1

Author Comment

ID: 40558672
@aikimark
No there will only be just 1 nr 1 and it needs to be moved to next available 0.

@gelonida

if my examplelist is
``````[0,1,0,2,0]
``````
then the processed list should look like this:
``````[0,0,1,2,0]
``````
My item 1 must always move forward to the next available 0 but your solution seems to pick first available 0 and show the list like this:
``````[1,0,0,2,0]
``````

I actually managed to get it working but I'm just a newbie to programming and I think that there should be a way better method to do this:

``````examplelist = [0,0,1,0,0]
print examplelist

zero1 = []
zero2 = []
for i, j in enumerate(examplelist):
if j == 1:
x = i

for i, j in enumerate(examplelist):
if i > x and j == 0:
zero1.append(i)

for i, j in enumerate(examplelist):
if i < x and j == 0:
zero2.append(i)

if zero1:
examplelist[zero1[0]]=1
examplelist[x]=0
elif zero2:
examplelist[zero2[0]]=1
examplelist[x]=0

print examplelist
``````
0

LVL 45

Expert Comment

ID: 40558691
you've changed the requirement.  You originally stated that the first available 0 was the swap partner with the 1.  Now you seem to be saying it is the next 0 position AFTER the 1, wrapping around to the beginning of the list.
0

LVL 1

Author Comment

ID: 40558737
Sorry if I was unclear kind of hard to explain, but I wrote in bold in description that it was Next 0 not first.
Anyhow sorry for being unclear.
0

LVL 45

Expert Comment

ID: 40559052
What if there is no next zero?
What if there is no zero?
What if there is no one?
0

LVL 45

Expert Comment

ID: 40559059
This would seem like the simplest swap for the case when there is a zero after the one:
``````a=[2,1,0,2,0]
oneposn=a.index(1)
nextzeroposn=a[oneposn+1:].index(0)
a[nextzeroposn+oneposn+1], a[oneposn] = 1,0
a
[2, 0, 1, 2, 0]
``````
0

LVL 45

Accepted Solution

aikimark earned 400 total points
ID: 40559079
This snippet handles zeroes to the right or left conditions.
``````a=[2,0,0,2,1]
#a=[2,1,0,2,0]
if 1 in a and 0 in a:
oneposn=a.index(1)
try:
nextzeroposn=a[oneposn+1:].index(0)+oneposn+1
except:
nextzeroposn=a[:oneposn].index(0)

a[nextzeroposn], a[oneposn] = 1,0
``````

Of course, this code would probably be packaged in a function.
0

LVL 16

Assisted Solution

gelonida earned 100 total points
ID: 40559208
@aikimark: I agree question was phrased a little ambigiously if both of us got it wrong. I saw that the question is now changed to be less ambigious

@smyken: It's really best to give examples of a normal case and all special cases.
In your example this would have been having a 1 just moving to the first 0 right of it and one special case for a one having to move to the first 0 of the list as there's no more right of it.
It's also very important to know whether it can happen, that there is no 0 at all in the list.
If I understood you said there will be maximum one 1,

So does it mean, that there can be no 1 at all and that it is possible to have no 0 values?
What was good and important was, that you mentioned, that the list is short and has only 5 elements. Ths helps to understand, that you do not need a fast, optimized high performance solution.

aikimark's solution seems to fulfill the requirements you have. It would not be optimal for large lists list, but for length 5 the code should be perfect as it is simple and rather easy to understand.

From a Python point of view there's three interesting things in aikamark's code which you could look at:
1.)
if 1 in a  # allows to search in a list for a given element if a is a list,
# or for a sub string if a is a string or for a key if a is a dict

2.)
a[pos:]  # this is array slicing look at https://docs.python.org/2/tutorial/introduction.html and search for slicing

3.) the try and except keyword # this is python exception handling refer to https://docs.python.org/2/tutorial/errors.html
0

LVL 1

Author Comment

ID: 40559873
Thanks guys !
You have been both very helpful.
Next time I will try to write my Questions in a better manner.
0

LVL 45

Expert Comment

ID: 40560702
You can also use the second parameter of the Index() method to specify the starting position for the search.
Example:
``````a=[2,0,0,2,1]
#a=[2,1,0,2,0]
if 1 in a and 0 in a:
oneposn=a.index(1)
try:
nextzeroposn=a.index(0,oneposn+1)
except:
nextzeroposn=a[:oneposn].index(0)

a[nextzeroposn], a[oneposn] = 1,0
``````
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

### Suggested Solutions

topping3 challenge 14 78
silent install of security banner via msiexec command 4 86
Path to Python 9 118
Advice on Xojo as a development tool over VB. 4 52
This is an explanation of a simple data model to help parse a JSON feed
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
Learn the basics of strings in Python: declaration, operations, indices, and slicing. Strings are declared with quotations; for example: s = "string": Strings are immutable.: Strings may be concatenated or multiplied using the addition and multiplic…
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…