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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.