This question already has answers here:
What is the easiest way to push an element to the beginning of the array?
(7 answers)
Closed 8 years ago.
What is the best way to prepend to an array in Ruby. Perhaps something similar to Python's list.insert(0, 'foo')?
I'd like to be able to add an element to a Ruby array at the 0 position and have all other elements shifted along.
array = ['b', 'c']
array.unshift('a')
p array
=> ['a', 'b', 'c']
As Scott G has pointed out in the comments, as of Ruby 2.5.0 #prepend has been added as an alias for #unshift.
Another way than Steve's answer
array = ['b', 'c']
array = ['a'] + array #["a", "b", "c"]
array = ["b", "c"]
array.insert(0, "a", "a") # => ["a", "a", "b", "c"]
Related
Let's say I have this array
array = ['a', 'b', 'c', 'd']
What is a good way to target an element (for example 'b') and switch it with the next element in line (in this case 'c') so the outcome becomes:
=> ['a', 'c', 'b', 'd']
array[1], array[2] = array[2], array[1]
array #=> ["a", "c", "b", "d"]
or
array[1, 2] = array.values_at(2, 1)
array #=> ["a", "c", "b", "d"]
There is no build in function to do this. You can swap the values like so:
array = %w[a b c d]
array[1..2] = array[1..2].reverse
array #=> ["a", "c", "b", "d"]
You could add some helper methods to the core array class.
class Array
def move_up(index)
self[index, 2] = self[index, 2].reverse
self
end
def move_down(index)
move_up(index - 1)
end
end
Note: Keep in mind that this solution mutates the original array. You could also opt for a version that creates a new array. For this version you can call #dup (result = dup) than work with result instead of self.
References:
Array#[]
Array#[]=
Array#reverse
Object#dup
Try this for swapping
array[0],array[1] = array[1],array[0]
or in general
array[i],array[i+1] = array[i+1],array[i]
Assuming that you want to target the elements by their indices, a combination of insert and delete_at would work:
array = %w[a b c d]
array.insert(2, array.delete_at(1))
array
#=> ["a", "c", "b", "d"]
Can someone please explain the difference in output between these two cases:
array = [['a', 'a,'], ['a', 'a']]
# => [['a', 'a,'], ['a', 'a']]
array[0][0] = 'b'
# => 'b'
array
# => [['b', 'a'], ['a', 'a']]
and
array = [['a'] * 2] * 2
# => [['a', 'a,'], ['a', 'a']]
array[0][0] = 'b'
# => 'b'
array
# => [['b', 'a'], ['b', 'a']]
It seems when using the form [['a'] * 2] * 2 to create the multi-dimensional array, changes to the first 'row' are duplicated in every row?
Is there an alternative short-form way to define a multidimensional array that doesn't have this behaviour?
The issue with your second technique is that you are creating a single array ['a', 'a'] and putting it in both positions in the array array. You need to clone the items in array so they aren't literally the same item.
array = [['a'] * 2] * 2
# => [["a", "a"], ["a", "a"]]
array.map! { |item| item.clone }
# => [["a", "a"], ["a", "a"]]
array[0][0] = 'b'
# => "b"
array
# => [["b", "a"], ["a", "a"]]
When you write [['a'] * 2] * 2 you are creating a single Array Object ['a', 'a'] with two references to it in the outer Array. To accomplish what you want you'd have to write.
array = []
2.times do
array << ['a']*2
end
This way you're creating a new inner array at each iteration and they should be independent from one another.
I'm looking for an elegant way to partition an array by using index in ruby
eg:
["a","b",3,"c",5].partition_with_index(2)
=> [["a","b",3],["c",5]]
So far the best that I can think is using the below
["a","b",3,"c",5].partition.each_with_index{|val,index| index <= 2}
=> [["a","b",3],["c",5]]
Is there any other elegant way to accomplish this?
Thanks!
You can do:
["a","b",3,"c",5].partition.with_index { |_, index| index <= 2 }
Following #toro2k advice, I think this is a better solution because you are combining the two Enumerators to get the desired output.
If you don’t pass a block of code to partition, it returns an Enumerator object instead. Enumerators have a with_index method that will maintain the current loop index.
Why don't you use array.slice!
array#slice! Deletes the element(s) given by an index (optionally up to length elements) or by a range.
> a = ['a', 'b', 'c', 5]
> b = a.slice! 0, 2 # => ['a', 'b']
> a # => ['c', 5]
In your case,
> [a.slice!(0, index), a]
You could use Enumerable's take and drop methods:
a = ["a","b",3,"c",5]
[a.take(3), a.drop(3)] # => [["a", "b", 3], ["c", 5]]
I made an Enumerable quick reference sheet you might want to consult for questions like this.
This can be done, but not sure if it elegant or not :
a = ["a","b",3,"c",5]
index = 2
[a[0..index], a[index+1..-1]]
Thanks
You can try the below :
a = ["a","b",3,"c",5]
par = a.slice_before(sum: -2) do |elem, state|
state[:sum] += 1
state[:sum] == 2
end.to_a
par
# => [["a", "b", 3], ["c", 5]]
For your particular case, 'pyper' gem is usable:
require 'pyper' # gem install pyper if necessary
include Pyper
ary = ["a", "b", 3, "c", 5]
ary.τ3τ #=> ["a", "b", 3]
ary.τfτ #=> ["c", 5]
It only works easily on small n (number of chopped-off elements), but Pyper provides many other frequently encountered tasks on collections. It was inspired by lisp's car and cdr functions (see details by an anonymous donor), and the letters can be combined together into a control string, a bit like in APL. Greek tau (τ) is used to denote methods instead of c and r, so car, cdr become τaτ, τdτ:
ary.τaτ #=> "a"
ary.τdτ #=> ["b", 3, "c", 5]
# Instead of τfτ, one can write
ary.τdddτ #=> ["c", 5]
etc.
Given some array such as the following:
x = ['a', 'b', 'b', 'c', 'a', 'a', 'a']
I want to end up with something that shows how many times each element repeats sequentially. So maybe I end up with the following:
[['a', 1], ['b', 2], ['c', 1], ['a', 3]]
The structure of the results isn't that important... could be some other data types of needed.
1.9 has Enumerable#chunk for just this purpose:
x.chunk{|y| y}.map{|y, ys| [y, ys.length]}
This is not a general solution, but if you only need to match single characters, it can be done like this:
x.join.scan(/(\w)(\1*)/).map{|x| [x[0], x.join.length]}
Here's one line solution. The logic same as Matt suggested, though, works fine with nil's in front of x:
x.each_with_object([]) { |e, r| r[-1] && r[-1][0] == e ? r[-1][-1] +=1 : r << [e, 1] }
Here's my approach:
# Starting array
arr = [nil, nil, "a", "b", "b", "c", "a", "a", "a"]
# Array to hold final values as requested
counts = []
# Array of previous `count` element
previous = nil
arr.each do |letter|
# If this letter matches the last one we checked, increment count
if previous and previous[0] == letter
previous[1] += 1
# Otherwise push a new array for letter/count
else
previous = [letter, 1]
counts.push previous
end
end
I should note that this doesn't suffer from the same problem that Matt Sanders describes, since we're mindful of our first time through the iteration.
Given an array ['a', 'b', 'c', 'd', 'e', 'f'], how would I get a list of all subsets containing two, three, and four elements?
I'm quite new to Ruby (moving from C#) and am not sure what the 'Ruby Way' would be.
Check out Array#combination
Then something like this:
2.upto(4) { |n| array.combination(n) }
Tweaking basicxman's a little bit:
2.upto(4).flat_map { |n| array.combination(n).to_a }
#=> [["a", "b"], ["a", "c"], ["a", "d"], ..., ["c", "d", "e", "f"]]