0

I have a method that iterates over an array, does a bunch of stuff under certain conditions and depending on these conditions I would ALSO like to delete some of the elements. In order to keep track of the indexes I like to delete I converted the each in to an each_with_index loop and store the index of the elements that I like to delete in an array index_array. How can I delete exactly the items on those indexes in my original array? Looping over the index_array and using delete_at would change the original index. Please see below description of the scenario:

> my_array = [0,1,2,3,4,5,6,7]
> delete_these_indexes = [1,2,5]
the desired result is:
> my_array => [0,3,4,6,7,8]
1
  • Welcome to Stack Overflow. We'd like to see evidence of your effort toward solving this. As is it looks like you didn't try and want us to write it for you, which isn't what SO is for. Please read "How to Ask" and the linked pages. meta.stackoverflow.com/q/261592/12842 is useful to read too. Commented Jul 20, 2016 at 21:36

4 Answers 4

3

How about this?

my_array = [0, 1, 2, 3, 4, 5, 6, 7]
delete_these_indices = [1, 2, 5]

delete_these_indices.sort.reverse_each {|i| my_array.delete_at(i) }

p my_array
# => [0, 3, 4, 6, 7, 8]

It's important to delete from the end of the array, since deleting an item will change the indices of all subsequent items, ergo sort.reverse_each. If you know the array is already sorted, you can just do reverse_each.

If you don't care bout modifying the delete_these_indices array, you can be somewhat more terse:

delete_these_indices.sort!
my_array.delete_at(i) while (i = delete_these_indices.pop)

Again, you can skip sort! if you know delete_these_indices is already sorted.

Sign up to request clarification or add additional context in comments.

3 Comments

Hoped that there would be some ruby magic to do this, but this is also quite an elegant solution! Thanks
FWIW I've edited my answer with a slightly more terse solution.
It;s worth noting that if you package that in a method you need to add my_array as the last line.
1
keep_these_indexes = my_array.each_index.to_a - delete_these_indexes
  #=> [0, 3, 4, 6, 7]

If you wish to modify my_array (which appears to be the case):

my_array.replace(my_array.values_at(*keep_these_indexes))
  #=> [0, 3, 4, 6, 7]

If not:

new_array = my_array.values_at(*keep_these_indexes)

See Array#values_at.

4 Comments

the - operator doesn't work on indexes but on objects. it's a set operator on the content objects, not indexes
@jaydel, that's Array#-.
I don't follow. to_a returns an Array object, so your snippet my_array.each_index.to_a - delete_these_indexes isn't returning the difference by index but by value. Sorry if I'm being thick here. late in the day...
Oh, I think I follow you. I'm not wrong but I misunderstood what you're trying to do. you're identifying which indexes you want to keep, not which values. Apologies
0
delete_these_indexes.each_with_index do |val, i|
    my_array.delete_at(val - i)
end

deletes at the desired index taking into account how many have previously been deleted and adjusting for that

https://repl.it/CeHZ

2 Comments

Do the indexes change on each iteration? Meaning if you are trying to delete at indexes, 3 and 5, and delete index 3 first, has the content at index 5 moved to index 4?
@jaydel yes they do! Can be troublesome if you aren't expecting it
0

Probably not the best answer, but you can do this as well:

delete_at_indices.each {|ind| my_array[ind] = nil }
my_array.delete(nil)

Takes a first pass to conceptually invalidate the data at the specified indices, then the call to .delete will blow out any values that match what's passed in.

This solution assumes that you can define a value that isn't valid for your array. Using nil will be problematic if you're treating this as a sparsely populated array (where nil is a valid value)

Technically you're iterating through each array once, but that Gentleman's Agreement on what your deletable value might make some people uncomfortable

2 Comments

one corner case I've ignored unintentionally is if the any of the indices to delete are bigger than the size of the array to clean out.
Might I suggest my_array.compact! instead of my_array.delete(nil)?

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.