3

Simple ruby question. Lets say I have an array of 10 strings and I want to move elements at array[3] and array[5] into a totally new array. The new array would then only have the two elements I moved from the first array, AND the first array would then only have 8 elements since two of them have been moved out.

0

5 Answers 5

4

Use Array#slice! to remove the elements from the first array, and append them to the second array with Array#<<:

arr1 = ['Foo', 'Bar', 'Baz', 'Qux']
arr2 = []

arr2 << arr1.slice!(1)
arr2 << arr1.slice!(2)

puts arr1.inspect
puts arr2.inspect

Output:

["Foo", "Baz"]
["Bar", "Qux"]

Depending on your exact situation, you may find other methods on array to be even more useful, such as Enumerable#partition:

arr = ['Foo', 'Bar', 'Baz', 'Qux']
starts_with_b, does_not_start_with_b = arr.partition{|word| word[0] == 'B'}

puts starts_with_b.inspect
puts does_not_start_with_b.inspect

Output:

["Bar", "Baz"]
["Foo", "Qux"]
Sign up to request clarification or add additional context in comments.

Comments

2
a = (0..9).map { |i| "el##{i}" }
x = [3, 5].sort_by { |i| -i }.map { |i| a.delete_at(i) }
puts x.inspect
# => ["el#5", "el#3"]
puts a.inspect
# => ["el#0", "el#1", "el#2", "el#4", "el#6", "el#7", "el#8", "el#9"]

As noted in comments, there is some magic to make indices stay in place. This can be avoided by first getting all the desired elements using a.values_at(*indices), then deleting them as above.

4 Comments

why did you do #sort_by ?
@ArupRakshit: If I don't remove them in descending order, the indices get messed up. If I remove #3, #5 drops to position #4; if I then remove #5, I have removed "el#6" instead of "el#5". But if I remove them from the biggest index down, the smaller indices stay in place.
Further to @max's point, sort is not limited to arrays whose elements respond to -.
@CarySwoveland: No, but delete_at is. The array must contain integers, or the code would fail further down the line. I do agree that .sort.reverse is more readable though.
2

Code:

arr = ["null","one","two","three","four","five","six","seven","eight","nine"]

p "Array: #{arr}"

third_el = arr.delete_at(3)
fifth_el = arr.delete_at(4)
first_arr = arr
p "First array: #{first_arr}"

concat_el = third_el + "," + fifth_el
second_arr = concat_el.split(",")
p "Second array: #{second_arr}"

Output:

c:\temp>C:\case.rb
"Array: [\"null\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"s
even\", \"eight\", \"nine\"]"
"First array: [\"null\", \"one\", \"two\", \"four\", \"six\", \"seven\", \"eight
\", \"nine\"]"
"Second array: [\"three\", \"five\"]"

Comments

0

Why not start deleting from the highest index.

arr = ['Foo', 'Bar', 'Baz', 'Qux']
index_array = [2, 1]
new_ary = index_array.map { |index| arr.delete_at(index) }
new_ary # => ["Baz", "Bar"]
arr # => ["Foo", "Qux"]

Comments

0

Here's one way:

vals  = arr.values_at *pulls
arr   = arr.values_at *([*(0...arr.size)] - pulls)

Try it.

arr   = %w[Now is the time for all Rubyists to code]
pulls = [3,5]

vals  = arr.values_at *pulls
  #=>     ["time", "all"]
arr   = arr.values_at *([*(0...arr.size)] - pulls)
  #=>     ["Now", "is", "the", "for", "Rubyists", "to", "code"]

arr   = %w[Now is the time for all Rubyists to code]
pulls = [5,3]

vals  = arr.values_at *pulls
  #=>     ["all", "time"]
arr   = arr.values_at *([*(0...arr.size)] - pulls)
  #=>     ["Now", "is", "the", "for", "Rubyists", "to", "code"]

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.