Setting few hash parameters with same value but different keys - ruby

I have a construction in my application for which I need a hash like this:
{ 1 => [6,2,2], 2 => [7,4,5], (3..7) => [7,2,1] }
So I would like to have same value for keys 3, 4, 5, 6 and 7.
Sure above example doesn't work cause Ruby is intelligent and sets hash key as given: it sets range as key :) So I can only access my value as my_hash[(3..7)] and my_hash[3], my_hash[4] and so on are nil.
Sure I can have a check or construction outside of hash to do what I need, however I am curious if it is possible to set a hash like this without using any loops outside hash declaration? If not, what is most elegant one? Thanks!

You could subclass Hash to make it easier to construct such hashes:
class RangedHash < Hash
def []=(key, val)
if key.is_a? Range
key.each do |k|
super k, val
end
else
super key, val
end
end
end
It works the same as a normal hash, except when you use a Range key, it sets the given value at every point in the Range.
irb(main):014:0> h = RangedHash.new
=> {}
irb(main):015:0> h[(1..5)] = 42
=> 42
irb(main):016:0> h[1]
=> 42
irb(main):017:0> h[5]
=> 42
irb(main):018:0> h['hello'] = 24
=> 24
irb(main):019:0> h['hello']
=> 24

Is there anything especially wrong with this?
myhash = { 1 => [6,2,2], 2 => [7,4,5] }
(3..7).each { |k| myhash[k] = [7,2,1] }

I don't think there's a way to set multiple keys using literal hash syntax, or without some iteration, but here's a short way to do it with iteration:
irb(main):007:0> h = { 1 => [6,2,2], 2 => [7,4,5] }; (3..7).each {|n| h[n] = [7,2,1]}; h
=> {1=>[6, 2, 2], 2=>[7, 4, 5], 3=>[7, 2, 1], 4=>[7, 2, 1], 5=>[7, 2, 1], 6=>[7, 2, 1], 7=>[7, 2, 1]}
(Note that the trailing ; h is just for displaying purposes above.)

I don't like the idea of creating separate key/value pairs for every possible entry in a range. It's not scalable at all, especially for wide ranges. Consider this small range:
'a' .. 'zz'
which would result in 702 additional keys. Try ('a'..'zz').to_a for fun. Go ahead. I'll wait.
Instead of creating the keys, intercept the lookup. Reusing the RangedHash class name:
class RangedHash < Hash
def [](key)
return self.fetch(key) if self.key? key
self.keys.select{ |k| k.is_a? Range }.each do |r_k|
return self.fetch(r_k) if r_k === key
end
nil
end
end
foo = RangedHash.new
foo[1] = [6,2,2]
foo[2] = [7,4,5]
foo[3..7] = [7,2,1]
At this point foo looks like:
{1=>[6, 2, 2], 2=>[7, 4, 5], 3..7=>[7, 2, 1]}
Testing the method:
require 'pp'
3.upto(7) do |i|
pp foo[i]
end
Which outputs:
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
[7, 2, 1]
For any value in a range this outputs the value associated with that range. Values outside the range, but still defined in the hash, work normally, as does returning nil for keys that don't exist in the hash. And, it keeps the hash as small as possible.
The downside to this, or any solution to the question, is the keys that are ranges could overlap, causing collisions. In most of the proposed solutions, the keys would stomp on each other, which would/could end up returning bad values. This method won't do that because it'd take a direct conflict to overwrite a range-key.
To fix this would require deciding whether overlaps are allowed, and, if so, is it OK that the first one found is returned, or should there be logic that determines "best-fit", i.e., the smallest range that fits, or some other criteria entirely. Or, should overlaps be joined to make a larger range if the value is the same? It's a can of worms.

Patching Hash directly, but otherwise the same idea as Luke's...
class Hash
alias_method :orig_assign, '[]='
def []= k, v
if k.is_a? Range
k.each { |i| orig_assign i, v }
v
else
orig_assign k, v
end
end
end
t = {}
t[:what] = :ever
t[3..7] = 123
p t # => {5=>123, 6=>123, 7=>123, 3=>123, 4=>123, :what=>:ever}

Here is some more approach:
h = { 1 => [6,2,2], 2 => [7,4,5], (3..7) => [7,2,1] }
def my_hash(h,y)
h.keys.each do |x|
if (x.instance_of? Range) and (x.include? y) then
return p h[x]
end
end
p h[y]
end
my_hash(h,2)
my_hash(h,3)
my_hash(h,1)
my_hash(h,10)
my_hash(h,5)
my_hash(h,(3..7))
Output:
[7, 4, 5]
[7, 2, 1]
[6, 2, 2]
nil
[7, 2, 1]
[7, 2, 1]

Related

What is the right way to write ruby code?

I am solving the pyramid problem, in which an array is reduced to a single element over time by subtracting two consecutive numbers in each iteration.
input: [1, 5, 9, 2, 3, 5, 6]
iterations
[4, 4, -7, 1, 2, 1],
[0, -11, 8, 1, -1],
[-11, 19, -7, -2],
[30, -26, 5],
[-56, 31],
[87]
output: 87
What is the best way or ruby way to solve this problem? This can be done by inheriting array and making a new class, but I don't know how. Please help. I write this code to solve it:
a = [1,5,9,2,3,5,6]
class Array
def pyr
a = self.each_cons(2).to_a.map! { |e| e[1] - e[0] }
a
end
end
while a.length > 1
a = a.pyr
ans = a[0]
end
p ans
I see three ways to approach this.
Reopen the Array class
Sure, if in your particular ruby script/project this is an elementary functionality of an array, reopen the class. But if you are going to re-open a class, at least make sure the name is something meaningful. pyr? Why not write a full name, so no conflicts are possible, something like next_pyramid_iteration (I have never heard of this pyramid problem, so excuse me if I am way of base here).
Make a class inherit from Array
class Pyramid < Array
def next_iteration
self.each_const(2).map! { |e| e[1] - e[o] }
end
end
and then your calculation would become something like
pyramid = Pyramid.new([1,5,9,2,3,5,6])
while pyramid.length > 1
pyramid.next_iteration
end
pyramid[0]
Make a specific class to do the calculation
I am not quite sure what you are trying to achieve, but why not just make a specific class that knows how to calculate pyramids?
class PyramidCalculator
def initialize(arr)
#pyramid = arr
end
def calculate
while #pyramid.length > 1
do_next_iteration
end
#pyramid.first
end
def self.calculate(arr)
PyramidCalculator.new(arr).calculate
end
protected
def do_next_iteration
#pyramid = #pyramid.each_const(2).map! { |e| e[1] - e[o] }
end
end
because I added a convenience class-method, you can now calculate a result as follows:
PyramidCalculator.calculate([1,5,9,2,3,5,6])
My personal preference would be the last option :)
I would just do it as a two-liner.
a = a.each_cons(2).map{|e1, e2| e2 - e1} while a[1]
a.first # => 87
It's certainly easy enough to turn this into a simple function without hacking on the Array class:
def pyr(ary)
return ary[0] if ary.length < 2
pyr(ary.each_cons(2).map { |e| e[1] - e[0] })
end
p pyr [1,5,9,2,3,5,6] # => 87
Use return ary if you want the answer as a one-element array rather than a scalar.
If you prefer iteration to recursion or have a very large array:
def pyr(ary)
ary = ary.each_cons(2).map { |e| e[1] - e[0] } while ary.length > 1
ary
end
By encapsulating this as a function rather than doing it inline, you get the ability to do the operation on any number of arrays plus it's non-destructive on the original input array.
It's not necessary to compute the end value by successive computation of differences, which requires (n*(n-1)/2 subtractions and the same number of additions, where n is the size of the array a. Instead, we can compute that value by summing n terms of the form:
(-1)K+ibin_coeff(n-1,i)*a[i]
for i = 0..(n-1), where:
K equals 0 if the array has an even number of elements, else K equals 1; and
bin_coeff(n,i) is the binomial coefficient for choosing "n items i at a time" (n!/i!*(n-i)!).
I know what you're thinking: the calculation of each binomial coefficient will take some work. True, but that can be done in an efficient way (which I've not done below), by computing bin_coeff(n-1,i+1) from bin_coeff(n-1,i), etc. Of course, that's academic, as no one is likely to actually use the method I'm suggesting.
(I'm hoping nobody will demand a proof, but I'll try to oblige if a request is made.)
Code
class Fixnum
def factorial
(1..self).reduce(1) { |t,i| t*i }
end
def bin_coeff m
self.factorial/(m.factorial*(self-m).factorial)
end
end
def pyramid_sum(a)
n = a.size-1
sign = n.even? ? -1 : 1
(0..n).reduce(0) do |t,i|
sign = -sign
t + sign * n.bin_coeff(i) * a[i]
end
end
Examples
pyramid_sum [1, 5] #=> 4
pyramid_sum [1, 5, 9] # #=> 0
pyramid_sum [1, 5, 9, 2] #=> -11
pyramid_sum [1, 5, 9, 2, 3] #=> 30
pyramid_sum [1, 5, 9, 2, 3, 5] #=> -56
pyramid_sum [1, 5, 9, 2, 3, 5, 6] #=> 87

How to preserve alphabetical order of keys when sorting a hash by the value

beginner here. My first question. Go easy on me.
Given the following hash:
pets_ages = {"Eric" => 6, "Harry" => 3, "Georgie" => 12, "Bogart" => 4, "Poly" => 4,
"Annie" => 1, "Dot" => 3}
and running the following method:
pets_ages.sort {|x, y| x[1] <=> y[1]}.to_h
the following is returned:
{
"Annie" => 1,
"Dot" => 3,
"Harry" => 3,
"Poly" => 4,
"Bogart" => 4,
"Eric" => 6,
"Georgie" => 12
}
You will notice the hash is nicely sorted by the value, as intended. What I'd like to change is the ordering of the keys, so that they remain alphabetical in the case of a tie. Notice "Dot" and "Harry" are correct in that regard, but for some reason "Poly" and "Bogart" are not. My theory is that it is automatically sorting the keys by length in the case of a tie, and not alphabetically. How can I change that?
In many languages, Hashes/Dicts aren't ordered, because of how the are implemented under the covers. Ruby 1.9+ is nice enough to guarantee ordering.
You can do this in a single pass - Ruby allows you to sort by arbitrary criteria.
# Given
pets_ages = {"Eric" => 6, "Harry" => 3, "Georgie" => 12, "Bogart" => 4, "Poly" => 4, "Annie" => 1, "Dot" => 3}
# Sort pets by the critera of "If names are equal, sort by name, else, sort by age"
pets_ages.sort {|(n1, a1), (n2, a2)| a1 == a2 ? n1 <=> n2 : a1 <=> a2 }.to_h
# => {"Annie"=>1, "Dot"=>3, "Harry"=>3, "Bogart"=>4, "Poly"=>4, "Eric"=>6, "Georgie"=>12}
Hash#sort will return an array of [k, v] pairs, but those k, v pairs can be sorted by any criteria you want in a single pass. Once we have the sorted pairs, we turn it back into a Hash with Array#to_h (Ruby 2.1+), or you can use Hash[sorted_result] in earlier versions, as Beartech points out.
You could get as complex as you want in the sort block; if you're familiar with Javascript sorting, Ruby actually works the same here. The <=> method returns -1, 0, or 1 depending on how the objects compare to each other. #sort just expects one of those return values, which tells it how the two given values relate to each other. You don't even have to use <=> at all if you don't want to - something like this is equivalent to the more compact form:
pets_ages.sort do |a, b|
if a[1] == b[1]
if a[0] > b[0]
1
elsif a[0] < b[0]
-1
else
0
end
else
if a[1] > b[1]
1
elsif a[1] < b[1]
-1
end
end
end
As you can see, as long as you always return something in the set (-1 0 1), your sort function can do whatever you want, so you can compose them however you'd like. However, such verbose forms are practically never necessary in Ruby, because of the super handy <=> operator!
As Stefan points out, though, you have a BIG shortcut here: Array#<=> is nice enough to compare each entry between the compared arrays. This means that we can do something like:
pets_ages.sort {|a, b| a.reverse <=> b.reverse }.to_h
This takes each [k, v] pair, reverses it into [v, k], and uses Array#<=> to compare it. Since you need to perform this same operation on each [k, v] pair compared, you can shortcut it even further with #sort_by
pets_ages.sort_by {|k, v| [v, k] }.to_h
What this does is for each hash entry, it passes the key and value to the block, and the return result of the block is what is used to compare this [k, v] pair to other entries. Since comparing [v, k] to another [v, k] pair will give us the result we want, we just return an array consisting of [v, k], which sort_by collects and sorts the original [k, v] pairs by.
As Philip pointed out, hashes were not meant to preserve order, though I think in the latest Ruby they might. But let's say they don't. Here's an array based solution that could then be re-hashed:
Edit here it is in a one-liner:
new_pets_ages = Hash[pets_ages.sort.sort_by {|a| a[1]}]
previous answer:
pets_ages = {"Eric" => 6, "Harry" => 3, "Georgie" => 12, "Bogart" => 4, "Poly" => 4,
"Annie" => 1, "Dot" => 3}
arr = pets_ages.sort
# [["Annie", 1], ["Bogart", 4], ["Dot", 3], ["Eric", 6], ["Georgie", 12],
# ["Harry", 3], ["Poly", 4]]
new_arr = arr.sort_by {|a| a[1]}
#[["Annie", 1], ["Dot", 3], ["Harry", 3], ["Bogart", 4], ["Poly", 4], ["Eric", 6],
# ["Georgie", 12]]
And finally to get a hash back:
h = Hash[new_arr]
#{"Annie"=>1, "Dot"=>3, "Harry"=>3, "Bogart"=>4, "Poly"=>4, "Eric"=>6,
# "Georgie"=>12}
So when we sort a hash, it gives us an array of arrays with the items sorted by the original keys. Then we sort that array of arrays by the second value of each, and since it's a lazy sort, it only shifts them if need be. Then we can send it back to a hash. I'm sure there's a trick way to do a two-pass sort in one line but this seems pretty simple.
As you already know few methods of ruby for sorting that you have used. So I would not explain it you in detail rather keep it very simple one liner for you. Here is your answer:
pets_ages.sort.sort_by{|pets| pets[1]}.to_h
Thanks

What is clearest way to add up all elements in 2 dimensional array by position using Ruby?

What is the clearest and most efficient way to add all the elements in 2D array by their position in Ruby. Example:
2darray = [[1,2,3],[1,2,3]]
result = [2,4,6]
I have the following code
def sum_elements_by_position(array)
total_elements = array.length
result = []
for i in 0...array.first.length
n = 0
array.each { |subarray| n += subarray[i] }
result << n
end
result
end
Assumptions: All primary elements are of the same length
For bonus points it would be great to see a solution that works primary elements of an arbitrary length
You can zip the first row with the rest of them and then do the sum:
def sum_elements_by_position(array)
array[0].zip(*array[1..-1]).map do |col|
col.inject(:+)
end
end
Here's a solution addressing when the rows aren't the same length.
def sum_cols arr
arr.reduce( [] ) do |res,row|
row.each_with_index { |e,i| res[i] ||= 0; res[i] += e }
res
end
end
irb> sum_cols [ [0,1,2], [3,4], [5,6,7,8] ]
=> [8, 11, 9, 8]
#oldergod suggested using zip based on the longest row, but finding the longest row and rejecting nils has a cost. I benchmarked the following against the above method using the example array above and found the reduce+each_with_index method more than 30% faster:
def sum_cols_using_zip arr
max_len = arr.map(&:size).max
([0] * max_len).zip(*arr).map do |col|
col.compact.inject(:+)
end
end
I'd do this:
a.transpose.map {|x| x.reduce(:+)}
Clean, simple, flexible. The .transpose turns this
[[1,2,3,4],[2,3,4,5],[3,4,5,6]]
into this
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
and then .map applies .reduce to each subarray. And .reduce, in turn, aggregates the subvalues by adding them. Or, more precisely, by applying the + method to them.
I highly recommend reading the doc for these functions until you fully understand this example, as it's a pretty good succinct demonstration of how to think in a Rubyish way!

How to map and remove nil values in Ruby

I have a map which either changes a value or sets it to nil. I then want to remove the nil entries from the list. The list doesn't need to be kept.
This is what I currently have:
# A simple example function, which returns a value or nil
def transform(n)
rand > 0.5 ? n * 10 : nil }
end
items.map! { |x| transform(x) } # [1, 2, 3, 4, 5] => [10, nil, 30, 40, nil]
items.reject! { |x| x.nil? } # [10, nil, 30, 40, nil] => [10, 30, 40]
I'm aware I could just do a loop and conditionally collect in another array like this:
new_items = []
items.each do |x|
x = transform(x)
new_items.append(x) unless x.nil?
end
items = new_items
But it doesn't seem that idiomatic. Is there a nice way to map a function over a list, removing/excluding the nils as you go?
You could use compact:
[1, nil, 3, nil, nil].compact
=> [1, 3]
I'd like to remind people that if you're getting an array containing nils as the output of a map block, and that block tries to conditionally return values, then you've got code smell and need to rethink your logic.
For instance, if you're doing something that does this:
[1,2,3].map{ |i|
if i % 2 == 0
i
end
}
# => [nil, 2, nil]
Then don't. Instead, prior to the map, reject the stuff you don't want or select what you do want:
[1,2,3].select{ |i| i % 2 == 0 }.map{ |i|
i
}
# => [2]
I consider using compact to clean up a mess as a last-ditch effort to get rid of things we didn't handle correctly, usually because we didn't know what was coming at us. We should always know what sort of data is being thrown around in our program; Unexpected/unknown data is bad. Anytime I see nils in an array I'm working on, I dig into why they exist, and see if I can improve the code generating the array, rather than allow Ruby to waste time and memory generating nils then sifting through the array to remove them later.
'Just my $%0.2f.' % [2.to_f/100]
Try using reduce or inject.
[1, 2, 3].reduce([]) { |memo, i|
if i % 2 == 0
memo << i
end
memo
}
I agree with the accepted answer that we shouldn't map and compact, but not for the same reasons.
I feel deep inside that map then compact is equivalent to select then map. Consider: map is a one-to-one function. If you are mapping from some set of values, and you map, then you want one value in the output set for each value in the input set. If you are having to select before-hand, then you probably don't want a map on the set. If you are having to select afterwards (or compact) then you probably don't want a map on the set. In either case you are iterating twice over the entire set, when a reduce only needs to go once.
Also, in English, you are trying to "reduce a set of integers into a set of even integers".
Ruby 2.7+
There is now!
Ruby 2.7 is introducing filter_map for this exact purpose. It's idiomatic and performant, and I'd expect it to become the norm very soon.
For example:
numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]
In your case, as the block evaluates to falsey, simply:
items.filter_map { |x| process_x url }
"Ruby 2.7 adds Enumerable#filter_map" is a good read on the subject, with some performance benchmarks against some of the earlier approaches to this problem:
N = 100_000
enum = 1.upto(1_000)
Benchmark.bmbm do |x|
x.report("select + map") { N.times { enum.select { |i| i.even? }.map{ |i| i + 1 } } }
x.report("map + compact") { N.times { enum.map { |i| i + 1 if i.even? }.compact } }
x.report("filter_map") { N.times { enum.filter_map { |i| i + 1 if i.even? } } }
end
# Rehearsal -------------------------------------------------
# select + map 8.569651 0.051319 8.620970 ( 8.632449)
# map + compact 7.392666 0.133964 7.526630 ( 7.538013)
# filter_map 6.923772 0.022314 6.946086 ( 6.956135)
# --------------------------------------- total: 23.093686sec
#
# user system total real
# select + map 8.550637 0.033190 8.583827 ( 8.597627)
# map + compact 7.263667 0.131180 7.394847 ( 7.405570)
# filter_map 6.761388 0.018223 6.779611 ( 6.790559)
Definitely compact is the best approach for solving this task. However, we can achieve the same result just with a simple subtraction:
[1, nil, 3, nil, nil] - [nil]
=> [1, 3]
In your example:
items.map! { |x| process_x url } # [1, 2, 3, 4, 5] => [1, nil, 3, nil, nil]
it does not look like the values have changed other than being replaced with nil. If that is the case, then:
items.select{|x| process_x url}
will suffice.
If you wanted a looser criterion for rejection, for example, to reject empty strings as well as nil, you could use:
[1, nil, 3, 0, ''].reject(&:blank?)
=> [1, 3, 0]
If you wanted to go further and reject zero values (or apply more complex logic to the process), you could pass a block to reject:
[1, nil, 3, 0, ''].reject do |value| value.blank? || value==0 end
=> [1, 3]
[1, nil, 3, 0, '', 1000].reject do |value| value.blank? || value==0 || value>10 end
=> [1, 3]
You can use #compact method on the resulting array.
[10, nil, 30, 40, nil].compact => [10, 30, 40]
each_with_object is probably the cleanest way to go here:
new_items = items.each_with_object([]) do |x, memo|
ret = process_x(x)
memo << ret unless ret.nil?
end
In my opinion, each_with_object is better than inject/reduce in conditional cases because you don't have to worry about the return value of the block.
One more way to accomplish it will be as shown below. Here, we use Enumerable#each_with_object to collect values, and make use of Object#tap to get rid of temporary variable that is otherwise needed for nil check on result of process_x method.
items.each_with_object([]) {|x, obj| (process x).tap {|r| obj << r unless r.nil?}}
Complete example for illustration:
items = [1,2,3,4,5]
def process x
rand(10) > 5 ? nil : x
end
items.each_with_object([]) {|x, obj| (process x).tap {|r| obj << r unless r.nil?}}
Alternate approach:
By looking at the method you are calling process_x url, it is not clear what is the purpose of input x in that method. If I assume that you are going to process the value of x by passing it some url and determine which of the xs really get processed into valid non-nil results - then, may be Enumerabble.group_by is a better option than Enumerable#map.
h = items.group_by {|x| (process x).nil? ? "Bad" : "Good"}
#=> {"Bad"=>[1, 2], "Good"=>[3, 4, 5]}
h["Good"]
#=> [3,4,5]

Create two-dimensional arrays and access sub-arrays in Ruby

I wonder if there's a possibility to create a two dimensional array and to quickly access any horizontal or vertical sub array in it?
I believe we can access a horizontal sub array in the following case:
x = Array.new(10) { Array.new(20) }
x[6][3..8] = 'something'
But as far as I understand, we cannot access it like this:
x[3..8][6]
How can I avoid or hack this limit?
There are some problems with 2 dimensional Arrays the way you implement them.
a= [[1,2],[3,4]]
a[0][2]= 5 # works
a[2][0]= 6 # error
Hash as Array
I prefer to use Hashes for multi dimensional Arrays
a= Hash.new
a[[1,2]]= 23
a[[5,6]]= 42
This has the advantage, that you don't have to manually create columns or rows. Inserting into hashes is almost O(1), so there is no drawback here, as long as your Hash does not become too big.
You can even set a default value for all not specified elements
a= Hash.new(0)
So now about how to get subarrays
(3..5).to_a.product([2]).collect { |index| a[index] }
[2].product((3..5).to_a).collect { |index| a[index] }
(a..b).to_a runs in O(n). Retrieving an element from an Hash is almost O(1), so the collect runs in almost O(n). There is no way to make it faster than O(n), as copying n elements always is O(n).
Hashes can have problems when they are getting too big. So I would think twice about implementing a multidimensional Array like this, if I knew my amount of data is getting big.
rows, cols = x,y # your values
grid = Array.new(rows) { Array.new(cols) }
As for accessing elements, this article is pretty good for step by step way to encapsulate an array in the way you want:
How to ruby array
You didn't state your actual goal, but maybe this can help:
require 'matrix' # bundled with Ruby
m = Matrix[
[1, 2, 3],
[4, 5, 6]
]
m.column(0) # ==> Vector[1, 4]
(and Vectors acts like arrays)
or, using a similar notation as you desire:
m.minor(0..1, 2..2) # => Matrix[[3], [6]]
Here's a 3D array case
class Array3D
def initialize(d1,d2,d3)
#data = Array.new(d1) { Array.new(d2) { Array.new(d3) } }
end
def [](x, y, z)
#data[x][y][z]
end
def []=(x, y, z, value)
#data[x][y][z] = value
end
end
You can access subsections of each array just like any other Ruby array.
#data[0..2][3..5][8..10] = 0
etc
x.transpose[6][3..8] or x[3..8].map {|r| r [6]} would give what you want.
Example:
a = [ [1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25]
]
#a[1..2][2] -> [8,13]
puts a.transpose[2][1..2].inspect # [8,13]
puts a[1..2].map {|r| r[2]}.inspect # [8,13]
I'm quite sure this can be very simple
2.0.0p247 :032 > list = Array.new(5)
=> [nil, nil, nil, nil, nil]
2.0.0p247 :033 > list.map!{ |x| x = [0] }
=> [[0], [0], [0], [0], [0]]
2.0.0p247 :034 > list[0][0]
=> 0
a = Array.new(Array.new(4))
0.upto(a.length-1) do |i|
0.upto(a.length-1) do |j|
a[i[j]] = 1
end
end
0.upto(a.length-1) do |i|
0.upto(a.length-1) do |j|
print a[i[j]] = 1 #It's not a[i][j], but a[i[j]]
end
puts "\n"
end
Here is the simple version
#one
a = [[0]*10]*10
#two
row, col = 10, 10
a = [[0]*row]*col
Here is an easy way to create a "2D" array.
2.1.1 :004 > m=Array.new(3,Array.new(3,true))
=> [[true, true, true], [true, true, true], [true, true, true]]

Resources