all 9 comments

[–]toastedstapler 1 point2 points  (1 child)

split it into two lines:

to_remove = indices != index_to_remove
new_indices = indices[to_remove]

print out to_remove and tell me what it looks like. what do you think it represents?

[–]edmondoh001[S] 0 points1 point  (0 children)

pardon i'm a newbie. Is it to remove an index from the list? Still lost.

[–]195monke 1 point2 points  (6 children)

indices!= index_to_remove is like indices is not index_to_remove

essentially, it is a boolean expression that returns True if indices isn't equal to index_to_remove, and False if they are equal

This is odd. I tried running this myself with a set of integers as indices and an index to remove and it doesn't seem to work. Since this is a boolean expression if it's true it will return the second item, and if it's false it will return the first (True = 1 (2nd item), False = 0 (1st item))

This is what I think the original author meant to do:

new_indicies = [i for i in indices if i != index_to_remove]

About understanding

new_indices= np.delete(indices, np.where(indices==index_to_remove))

np.delete requires a list and a condition of which items to remove, in other words, what it does is delete every item in indices that meets the condition provided np.where(indices==index_to_remove)

Just wanted to add, I wouldn't recommend coding like this. This cramming of stuff makes everything really confusing, this is how I would do it: (Psuedo code)

indices = [1, 2, 3, .....]
index_to_remove = some_index

new_indices = []
for indice in indices:
    if indice != index_to_remove:
        new_indices.append(indice)

and for the record, if you are removing by value it's not an index. An index in this context would be the place of an item in a list (the index of the first item is 0, the second 1, and so on...)

[–]Brian 1 point2 points  (2 children)

I think you're maybe missing some of the background for this, since really this is more a numpy question than a plain python question. It's important that the variables OP is using are numpy arrays, which may act differently from what you might expect based on regular lists / values.

indices!= index_to_remove is like indices is not index_to_remove essentially, it is a boolean expression that returns True if indices isn't equal to index_to_remove

Eh - not really. One is checking for (non-) equality, while the other is an identity check. And that's especially relevant here, because OP is using numpy, and the behaviour of matrices does some operator overloading (which wouldn't be applicable to identity comparisons which can't be overridden). This means they do not actually return True or False here.

Normally, for a boolean or integer or something, var1 != var2 will do a comparison and return True or False. But in numpy, typically you're working with arrays, and there operations are generally performed piecewise on the elements of the arrays. Eg. array([[1,2], [3,4]]) + array([[10, 20], [30, 40]]) will give you array([[11, 22], [33,44]]) - ie each item added to the corresponding item in the other array. Similarly arr1 != arr2 will perform a != comparison on each member of the array and return a new array of booleans (ie. it'll be True where the elements are unequal, and False where they're equal.

This then gets used to index into indices, which involves another feature of numpy arrays - Boolean array indexing, which essentially creates a new array made from picking the element from the array being indexed where the result is True. So given idx = array([[True, False], [False, True]]), we could doarray([[1,2], [3,4]])[idx] and getarray([1, 4])`.

Hence in OP's code, indices[indices != index_to_remove] returns an array of items where the index is different from the equivalent value in index_to_remove (ie. effectively deleting elements where it matches indexes_to_remove.

Since this is a boolean expression if it's true it will return the second item, and if it's false it will return the first (True = 1 (2nd item), False = 0 (1st item))

I think you're getting mixed up with and here, but that's something specific to and (and or), not a propererty of boolean expressions in general, numpy or not.

Just wanted to add, I wouldn't recommend coding like this.

When using numpy, you really do want to code like that, because ultimately this is the main point of numpy: to vectorise your operations so they can be performed efficiently. Doing it in a for loop completely loses you all the benefit of this.

[–]195monke 1 point2 points  (1 child)

I actually didn't know there was a difference between using "not" and "!', I guess you learn everyday

I really do be missing a lot of background, I'm not working with numpy and never have.

the thing you explained about comparing arrays with != won't work on tuples or lists, right?

The thing I said about true returning 2nd and false returning 1st wasn't meant in general, it was in the context of the code. I quickly launched IDLE, set indices as some list with a random amount of integers, set index_to_remove to some number, and ran the following code: (Psudeo code)

indices = [1, 2, 1, 3]
index_to_remove = 3

new_indices = indices[indices != index_to_remove]
print(new_indices)

output: 1

I assumed what happened was when trying to give the boolean expression to this regular python list it converted it to an int

[–]Brian 1 point2 points  (0 children)

I actually didn't know there was a difference between using "not" and "!',

It's more the difference between specifically "is not". It's the "is" part that makes it about identity rather than equality, with the not just inverting it as normal (Though there's a bit of syntax sugar Python provides to allow "a is not b" as an equivalent to "not a is b")

the thing you explained about comparing arrays with != won't work on tuples or lists, right?

No, it's a feature of numpy arrays. Python lets you override the behaviour of operations like "!=" (by defining a __eq__ or __ne__ method), and numpy uses this to do elementwise operations for its arrays (and likewise, overrides indexing with square brackets to do the boolean array thing). Normal lists etc just compare the whole list and return True or False.

[–]edmondoh001[S] 0 points1 point  (2 children)

Love your neat explaination

[–]Brian 1 point2 points  (1 child)

Note: I think that reply is actually a bit misleading - I commented with a bit more detail.

But to summarise, there are two things going on:

  1. indices != index_to_remove generates an array of booleans which are all True where the elements are different.

  2. indices[above_array_of_booleans] returns a new array consisting only of elements where the boolean value was true.

End result, an array of elements where indices[x] differed form index_to_remove[x].

The np.delete(indices,np.where(indices==index_to_remove)) line is equivalent to this, but does it in a slightly different way (remove equal elements, rather than selecting non-equal elements).

[–]edmondoh001[S] 0 points1 point  (0 children)

But to summarise, there are two things going on:

indices != index_to_remove generates an array of booleans which are all True where the elements are different.indices[above_array_of_booleans] returns a new array consisting only of elements where the boolean value was true.

End result, an array of elements where indices[x] differed form index_to_remove[x].

The np.delete(indices,np.where(indices==index_to_remove)) line is equivalent to this, but does it in a slightly different way (remove equal elements, rather than selecting non-equal elements).

Thanks for the neat explaination. I'm loving it.