简体   繁体   中英

Changing the elements of a list by iteration (python)

I'm trying to iterate through a list (range entered by user), at first assume that all numbers are prime (P), and have the program iterate through the list. When the element in the list is P, I want to iterate through all multiples within the range and change them to N. When the element is N, I want the program to move onto the next number (I set 0 and 1 to not prime, as they are exceptions). I'm running into an issue with indexing however, I get the error:

 list1[number1] = 'N'
IndexError: list assignment index out of range

When I run the program I have. Here is the code:

# input

n = int(input("Enter a positive integer greater than or equal to 10: "))

while n < 10:
    print ("Invalid! Try again")
    int(input("Enter a positive integer greater than or equal to 10: "))


# create list
new_n = n + 1

list1 = ['P'] * new_n


# set non prime
list1[0] = 'N'
list1[1] = 'N'

# set up loop

counter = 0 
for x in list1:
    counter1 = 2
    if list1[counter] == 'P':
        for y in list1:
            number1 = counter * counter1
            list1[number1] = 'N'
            counter1 += 1
            counter += 1 
    else:
        counter += 1 

Any help would be appreciated! Thanks.

In your loops, you're setting only squared value as non prime because you iterate counter in counter1 's loop.

Then you have to check if number1 is lesser than the size of list1 .

You also have to put counter+=1 outside else statement. Otherwise you'll set only multiples of 2 (once you withdraw counter+=1 from counter1 's loop).

So this code works:

# set up loop
counter = 0
for x in list1:
    counter1 = 2
    if list1[counter] == 'P':
        for y in list1:
            number1 = counter * counter1
            if number1 < len(list1):
                list1[number1] = 'N'
                counter1 += 1
    counter += 1

Besides, you should simplify your code using enumerate and range :

# set up loop
for i, val in enumerate(list1):
    if val == 'P':
        for j in range(2, len(list1)):
            if i*j < len(list1):
                list1[i*j] = 'N'
            else:
                break

Here's the result for n = 12:

 Enter a positive integer greater than or equal to 10: 12
 ['N', 'N', 'P', 'P', 'N', 'P', 'N', 'P', 'N', 'N', 'N', 'P', 'N']

Edit: Put counter+=1 outside else statement

list1[number1] = 'N'
IndexError: list assignment index out of range

That means that number1 is a bigger number than the total amount of items in the list.

The problem is in the line number1 = counter * counter1 . Lets say are 10 items in list1, by the time you got to using the number 10 as the counter you are going to be trying to access the 100th item in the list even though there are only 10 items in there. (counter * counter1 or 10 * 10 = 100 (actually the counter starts at 2 so it would be an even bigger number, but you get the point))

Also a nice little hint. Implementing a Sieve of Eratosthenes algorithm instead will greatly speed things up.

You may update your code like this:

# set up loop
for counter in range(len(list1)):
    if list1[counter] == 'P':
        number1 = 2 * counter
        while number1 < new_n:
            list1[number1] = 'N'
            number1 += counter

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM