The code below currently pushes a copy of #startyear into #new. I need to convert this into 1 single array, any ideas?
Forums didn't have much
startyear = [["a", "b", "z"], ["c", "d"], ["e", "f"], ["g", "h", "i", "j"]]
new = []
startyear.each do |n| #.transpose here?
puts "looping #{n}"
new.push(n)
#n.join is needed somewhere
puts "#{startyear.length} is the length of startyear"
break if startyear.length == startyear.length[4]
end
puts "your new array is : #{new}"
You can use Array#flatten:
startyear = [["a", "b", "z"], ["c", "d"], ["e", "f"], ["g", "h", "i", "j"]]
flattened = startyear.flatten
# flattened is now ["a", "b", "z", "c", "d", "e", "f", "g", "h", "i", "j"]
Array#flatten is the obvious method to use here, but as is generally the case with Ruby, there are alternatives. Here are two.
Use Enumerable#flat_map and Object#itself
startyear.flat_map(&:itself)
#=> ["a", "b", "z", "c", "d", "e", "f", "g", "h", "i", "j"]
itself was introduced in Ruby v2.2. For earlier versions, use:
startyear.flat_map { |a| a }
Use Enumerable#reduce (aka inject)
startyear.reduce(:+)
#=> ["a", "b", "z", "c", "d", "e", "f", "g", "h", "i", "j"]
Related
From the docs
"When the block returns zero, the order for a and b is indeterminate, and may be unstable:
a = 'abcde'.split('').shuffle
a # => ["e", "b", "d", "a", "c"]
a1 = a.sort {|a, b| 0 }
a1 # => ["c", "e", "b", "d", "a"]
"
If I run this code the sort appears to be stable:
puts RUBY_VERSION # => 3.0.3
p a = 'abcde'.split('').shuffle # => ["d", "e", "c", "b", "a"]
p a1 = a.sort {|a, b| 0 } # => ["d", "e", "c", "b", "a"]
Has Ruby sneakily got a stable sort?
Enumerable#map creates an array with the return values in the block after it's yielded.
In such case, say:
v = 'a'
26.times.map { |i| v.ord.+(i).chr }
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
But why does the following codes fills the array with same elements?
v = '`'
26.times.map { v.next! }
# => ["z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z"]
v = '`'
Array.new(26) { v.next! }
# => ["z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z"]
Shouldn't they all have elements a to z?
Again, this works:
v = '`'
Array.new(26) { v = v.succ }
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
Actually I am trying to do:
v = "\xf0\x9d\x93\xa9"
('a'..'z').reduce({}) { |h, i| h.merge(i.intern => v = v.succ) }
# => {:a=>"𝓪", :b=>"𝓫", :c=>"𝓬", :d=>"𝓭", :e=>"𝓮", :f=>"𝓯", :g=>"𝓰", :h=>"𝓱", :i=>"𝓲", :j=>"𝓳", :k=>"𝓴", :l=>"𝓵", :m=>"𝓶", :n=>"𝓷", :o=>"𝓸", :p=>"𝓹", :q=>"𝓺", :r=>"𝓻", :s=>"𝓼", :t=>"𝓽", :u=>"𝓾", :v=>"𝓿", :w=>"𝔀", :x=>"𝔁", :y=>"𝔂", :z=>"𝔃"}
But I get all z's instead while using succ! / next!
v = "\xf0\x9d\x93\xa9"
('a'..'z').reduce({}) { |h, i| h.merge(i.intern => v.succ!) }
# => {:a=>"𝔃", :b=>"𝔃", :c=>"𝔃", :d=>"𝔃", :e=>"𝔃", :f=>"𝔃", :g=>"𝔃", :h=>"𝔃", :i=>"𝔃", :j=>"𝔃", :k=>"𝔃", :l=>"𝔃", :m=>"𝔃", :n=>"𝔃", :o=>"𝔃", :p=>"𝔃", :q=>"𝔃", :r=>"𝔃", :s=>"𝔃", :t=>"𝔃", :u=>"𝔃", :v=>"𝔃", :w=>"𝔃", :x=>"𝔃", :y=>"𝔃", :z=>"𝔃"}
Except succ! / next! doesn't change the memory location and object_id, aren't v.succ! and v = v.succ same?
When you call next! or succ! on a variable str, object assigned to this variable is mutated and a reference to this object is returned. If str = 'a' and you call str.next! 26 times, str becomes z. Every time next! is called, a reference to the same object is returned. As a result, you get an array of 26 references to the same object. That's why all of the elements in the array are the same.
You can test that by checking object_id of array elements:
pry(main)> str = 'a'
'a'
pry(main)> array = 3.times.map{ str.next!}
=> ["d", "d", "d"]
pry(main)> array.map(&:object_id)
=> [47056742362940, 47056742362940, 47056742362940]
pry(main)> array.map(&:object_id).uniq
=> [47056742362940]
When you edit str, all array elements are updated:
[39] pry(main)> str << "b"
=> "db"
[40] pry(main)> array
=> ["db", "db", "db"]
[41] pry(main)> str.replace
str.replace
[41] pry(main)> str.replace('a')
=> "a"
[42] pry(main)> array
=> ["a", "a", "a"]
If you want to have an array with the whole alphabet, you need to copy the string after changing current letter, see below:
[25] pry(main)> str = 'a'
=> "a"
[26] pry(main)> 25.times.map{ str.next!.dup}
=> ["b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"w",
"x",
"y",
"z"]
You can also use a range:
[32] pry(main)> ('a'..'z').to_a
=> ["a",
"b",
"c",
"d",
"e",
"f",
...
I want to create an array of possibly repeated combinations of n elements from the letters A to F. Each combination should be an array. For n = 4 for example, the result should be:
[[A, A, A, A], [A, A, A, B], [A, A, A, C], ..., [F, F, F, F]]
without significance in order among the elements ([A, A, E, E] and [E, E, A, A] would be the same).
I tried it with:
('A'..'F').to_a.combination(4).to_a
but that didn't work. I guess the task is more complicated.
Try repeated_combination:
('A'..'F').to_a.repeated_combination(4).to_a
Example:
> ('A'..'C').to_a.repeated_combination(4).to_a
=> [["A", "A", "A", "A"], ["A", "A", "A", "B"], ["A", "A", "A", "C"], ["A", "A", "B", "B"], ["A", "A", "B", "C"], ["A", "A", "C", "C"], ["A", "B", "B", "B"], ["A", "B", "B", "C"], ["A", "B", "C", "C"], ["A", "C", "C", "C"], ["B", "B", "B", "B"], ["B", "B", "B", "C"], ["B", "B", "C", "C"], ["B", "C", "C", "C"], ["C", "C", "C", "C"]]
How to combine 2 arrays like this
a = ["x","y","z"]
b = [["a","b"],["c","d"],["e","f"]]
expected output:
[["a","b","x" ],["c","d","y"],["e","f","z"]]
Is there any inbuilt method?
There is. You can use Array#zip in conjunction with Array#flatten:
b.zip(a).map(&:flatten)
#=> [["a", "b", "x"], ["c", "d", "y"], ["e", "f", "z"]]
another way is:
[b, a].transpose.map(&:flatten)
#=> [["a", "b", "x"], ["c", "d", "y"], ["e", "f", "z"]]
:)
Here is one more way to do this:
a = ["x","y","z"]
b = [["a","b"],["c","d"],["e","f"]]
b.map.with_index {|arr, idx| arr << a[idx]}
#=> [["a", "b", "x"], ["c", "d", "y"], ["e", "f", "z"]]
enum = a.to_enum
b.map { |arr| arr << enum.next }
#=> [["a", "b", "x"], ["c", "d", "y"], ["e", "f", "z"]]
Say i have the following array:
array = ["a", "b", "c", "new", "d", "e", "f", "g", "new", "h", "i", "new"]
I want to create a new array every time I find the value "new".
So I would end up with:
array1 = ["a", "b", "c"]
array2 = ["d", "e", "f", "g"]
array3 = ["h", "i"]
What would be the best way to do this?
As the name implies you can split arrays with the split function, however that returns ArraySlice objects.
To get arrays back from the slices you need to map them (credits to Martin R)
let array = ["a", "b", "c", "new", "d", "e", "f", "g", "new", "h", "i", "new"]
let splittedArrays = array.split(separator: "new").map(Array.init)