简体   繁体   中英

Remove elements from a list, using another list as indices

I have a list primeList and another list ls . primeList is a list full of integers, and I need to delete the values from ls which have an index that is in primeList .

For example if primelist = [1, 3 , 5] and ls = [1, 2, 3, 4, 5, 6, 7] , then indexes 1, 3, and 5 should be removed from ls , making ls = [1, 3, 5, 7]

At the moment I'm trying to use this bit of code:

primeList = list(getPrimes())
    ls = list(ls)
    for i in primeList:
        del ls[i]
    return ls

This gives me the following error:

Traceback (most recent call last):
File "C:/Python34/My Scripts/NLP lab2/exec2.py", line 26, in <module>
otherList = delPrimes(myList)
File "C:/Python34/My Scripts/NLP lab2/exec2.py", line 18, in delPrimes
del ls[i]
IndexError: list assignment index out of range`

I believe this is because getPrimes is a larger list than ls, but I'm not sure how to work around this problem in Python?

EDIT - This is all of my current code:

def delPrimes(*ls):

def getPrimes():
    L = []
    for x in range(2, 230):
        isPrime = True
        for y in range(2, x):
            if x % y == 0:
                isPrime = False
        if isPrime:
            L.append(x)
    return L

primeList = list(getPrimes())
ls = list(ls)
for i in primeList:
    del ls[i]
return ls

  myList = list(range(1, 51))

  print(myList)
  print("--" * 40)

  otherList = delPrimes(myList)

  print(otherList)

As part of some schoolwork we need to "Write a method in Python to delete the items at prime index locations in a list (up to index location 50). Eg It will remove the item at index location 2, 3, 5, 7, … " I also believe we must use 'del' to do the deletion.

EDIT2:

for i in reversed(primeList):
        if i <= len(ls):
            del ls[i]
        else:
            continue
return ls

Use a list comprehension to avoid altering the list in place:

return [v for i, v in enumerate(ls) if i not in primeList]

You are deleting elements from the front of the list one by one, so the other elements each shift up one place. After the first deletion the rest of your indices are then off-by-one, then off-by-two, etc:

>>> ls = [1, 2, 3, 4, 5, 6, 7]
>>> del ls[1]
>>> ls
[1, 3, 4, 5, 6, 7]
>>> ls[3]
5
>>> del ls[3]
>>> ls
[1, 3, 4, 6, 7]
>>> ls[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

You can alter ls in place, but then you need to handle the indices in reverse so that you are only deleting indices that haven't yet shifted:

for index_to_remove in reversed(primeList):
    del ls[index_to_remove]

but since you are already making a copy that's not necessary here.

I see Martijn gave a complete answer before I did. His answer is correct, so I've upvoted him. If there's something unclear ask away. A comment on your code.

Your code is poorly pasted or it's incorrect. You have a return statement outside a function. Apart from that I'm going to try and guess what you intention was since the code is mushed.

If you use the * in you are doing something that's called unpacking values. I don't think that's necessary for what you need.

>>> def test(*ls):
        print ls
>>> test("a", "b", "c")
('a', 'b', 'c')
>>> ls = [1,2,3]
>>> test(ls)
([1, 2, 3],)

>>> def test(ls):
    print ls
>>> test("a", "b", "c")

Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    test("a", "b", "c")
TypeError: test() takes exactly 1 argument (3 given)

I'm not so sure you really meant to do that.

You could rewrite your getPrimes function as well, so that you don't need to spend time on calculating all those primes (granted it's currently a small number, but since I'm already giving "tips" why not)

def getPrimes(top):
    L = []
    for x in range(2, top+1):
        isPrime = True
        for y in range(2, x):
            if x % y == 0:
                isPrime = False
        if isPrime:
            L.append(x)
    return L

Now you can call that function like:

>>> getPrimes(7)
[2, 3, 5, 7]

Which can come useful even when your list is not always the same because you can always call the function by just asking.

>>> getPrimes(max(ls))
[2, 3, 5, 7]

Where max(ls) does the obvious and returns the largest element in the list (the highest prime you have). After that just follow Martijns instructions on how to delete the elements (reverse the order).

And since Python is dynamically typed language, you don't need to explicitly convert the returns of your functions into types. So the list isn't really necessary in the lines primeList = list(getPrimes()) and ls = list(ls) unless ls is not a list from the start. You most likely have that line because you have the unpacking operator * in your function which then returned ([1, 2, 3],) which is a type tuple (,) ("a pair of values") with a list [1,2,3] as first element.

Hope I helped clear some things out. Happy programing.

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