0

I have a kinda ugly snippet of code that takes an array a, skips the i-th element np.hstack([a[:i], a[i+1:]) of this array, and appends it to the result array. I wonder whether there is any fancy way (without manual for-loops) to do the following:

[a, b, c] -> [[b, c], [a, c], [a, b]]
3
  • I'm not entirely sure what you're asking, but you might be looking for the itertools combinations method. Commented Sep 13, 2019 at 13:15
  • What is the len of the array. How do you want it to be grouped. How many groups or arrays. Commented Sep 13, 2019 at 13:16
  • Can you actually show the array you are working with, as well as an expected output? Commented Sep 13, 2019 at 13:17

2 Answers 2

3

Here's one way with masking -

def skip_one(a):
    n = len(a)
    return np.repeat(a[None],n,axis=0)[~np.eye(n,dtype=bool)].reshape(n,-1)

Alternative #1 :

Save on memory with the replication, use np.broadcast_to(a,(n,n)) to replace np.repeat(a[None],n,axis=0).

Alternative #2 :

Replace last step with np.tile based code to bring in more compact-ness -

np.tile(a,(n,1))[~np.eye(n,dtype=bool)].reshape(n,-1)

Alternative #3 :

Use a custom made mask. Hence, replace the second step with -

np.broadcast_to(a,(n,n))[np.not_equal.outer(*[range(n)]*2)].reshape(n,-1)

Sample run -

In [22]: a
Out[22]: array([4, 7, 3, 8])

In [23]: skip_one(a)
Out[23]: 
array([[7, 3, 8],
       [4, 3, 8],
       [4, 7, 8],
       [4, 7, 3]])
Sign up to request clarification or add additional context in comments.

4 Comments

thanks, neat idea, but shouldn't the parameters of last reshape be in the tuple?
checked the ndarray.reshape docs, it allows to inline shape parameters
one more question, is not_equal more effective than using python != operator? I guess that not_equal exploits the knowledge of fixed array type making it faster, in comparison with searching for the implementation of __ne__
@andrhua Here that one has a method outer, which we need. So. it makes sense here.
0

You could do what (I presume) you did in a list comprehension:

[np.hstack((data[:i],data[i+1:])) for i in range(len(data))]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.