0

I have an array, let's say arr = [1, 2, 3, 4, 5, 6, 7, 8] and another indices array: idx = [0, 3, 4, 6]

and I want to get two arrays, one is only those indices from arr: [1, 4, 5, 7] and another one is all the rest: [2, 3, 6, 8]

Can someone help me with that? I can only think of ugly ways to do it, but it must be some function that does it elegantly.

Thanks a lot!

0

6 Answers 6

3

You could do it like this:

selected = [arr[i] for i in idx]
other = [v for i, v in enumerate(arr) if i not in idx]

If arr has no duplicates, you could also do:

other = [v for v in arr if v not in selected]
Sign up to request clarification or add additional context in comments.

1 Comment

Works great. Thanks a lot!
2

Way to do it:

a1 = [arr[x] for x in idx] 
a2 = [x for x in arr if x not in a1]

Comments

2

With one traversal:

no, yes = both = [], []
for i, x in enumerate(arr):
    both[i in idx].append(x)

Or (as commented by Chris_Rands):

yes, no = [], []
for i, x in enumerate(arr):
    (yes if i in idx else no).append(x)

Though idx should either be small for this or turned into a set (same goes for the solutions in the other answers, I guess they just don't want to talk about it).

Demo:

>>> if 1:
    arr = [1, 2, 3, 4, 5, 6, 7, 8]
    idx = [0, 3, 4, 6]
    no, yes = both = [], []
    for i, x in enumerate(arr):
        both[i in idx].append(x)
    print('yes', yes)
    print('no', no)

yes [1, 4, 5, 7]
no [2, 3, 6, 8]

3 Comments

@Chris_Rands Hmm, what if I rename both to noyes or no_yes?
Well it's subjective I guess, but personally I prefer the other way, plus it might be less confusing for beginners perhaps
@Chris_Rands Ok, I'll add it. I thought one reason I started using mine was that it was faster, but I just timed it again and it was slower. Thanks.
2

There is a neat solution with numpy:

import numpy as np

arr = np.asarray([1, 2, 3, 4, 5, 6, 7, 8])  # converts your list in numpy array
idx1 = [0, 3, 4, 6]
idx2 = [1, 2, 5, 7]

arr1 = arr[idx1]  # [1 4 5 7]
arr2 = arr[idx2]  # [2 3 6 8]

Comments

1

You can use itertools for a one line solution:

import itertools
arr = [1, 2, 3, 4, 5, 6, 7, 8]
idx = [0, 3, 4, 6]
[(out_index, not_in_arr), (in_index, in_arr)] = [(a, list(b)) for a, b in itertools.groupby(sorted(arr, key=lambda x:arr.index(x) in idx), key=lambda x:arr.index(x) in idx)]
print(not_in_arr)
print(in_arr)

Output:

[2, 3, 6, 8]
[1, 4, 5, 7]

Comments

0

You can also map each value in arr to a dictionary, indicating if it's index is present in idx:

arr = [1, 2, 3, 4, 5, 6, 7, 8]
idx = [0, 3, 4, 6]

# converted to a set
idx_lookup = set(idx)

d = {x: True if i in idx_lookup else False for i, x in enumerate(arr)}
print(d)

Which gives this dictionay:

{1: True, 2: False, 3: False, 4: True, 5: True, 6: False, 7: True, 8: False}

I also converted idx to a set since in this case, duplicate indices are not necessary, and set/dictionary lookup is O(1). However, list lookup is O(n), so this optimization is worth it if possible.

Once you have this dictionary, you can filter out the elements you want to keep, and the rest of the elements from this:

keep = list(filter(lambda x: d[x], arr))
rest = list(filter(lambda x: not d[x], arr))

print(keep)
print(rest)

Which Outputs:

[1, 4, 5, 7]
[2, 3, 6, 8]

Note: You can also use list comprehensions above filtering of keep and rest:

keep = [x for x in arr if d[x]]
rest = [x for x in arr if not d[x]]

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.