Limited matrices in Ruby
The designer of class Matrix
must have been a fan of immutable data structures and functional programming. Yes, you are correct.
In any case, there is a simple solution for what you want. Use Matrix
for what it can do, then, just use .to_a
to get a real array.
>> Matrix.identity(2).to_a
=> [[1, 0], [0, 1]]
See also Numerical Ruby Narray. You could also monkeypatch the class to add more behavior. If you do this, please patch a subclass of Matrix. (There are Ruby library projects out there that want more behavior from require
d classes so they directly modify them, making their new files somewhat toxic. They could have so easily just patched a subclass or singleton class.)
Oh, and khelll (:-) would probably like me to say that there is quite possibly a way for you to do what you want in a functional style. That is, by creating new objects rather than by modifying the old ones.
How to modify a matrix (Ruby std-lib Matrix class)?
You can open the class and def your own method to do this:
class Matrix
def []=(i, j, x)
@rows[i][j] = x
end
end
Ruby core Matrix vs NArray's NMatrix
Just stumbling on this question now... It's been 7 months since you've asked, so I'm sure you've found your answer by now.
However, please find information here.
Basically, the author of the core Matrix class did not add methods to perform run-time modifications to the array once it is instantiated. The NArray class allows for this.
As far as computation time, I'll leave that to somebody else, for I don't know.
Generate array of limited combinations from another array
You can use Array#permutation
if you don't want repetetions in the subarrays.
col
1 ∈ [1; 3]row
2 ∈ [0; 3]
days.permutation(col).to_a.slice(0, row)
Demonstration
If you want repetitions in the subarrays, you can use Array#repeated_permutation
.
col
∈ [1; 3]row
∈ [0; 33(= 27)]:
days.repeated_permutation(col).to_a.slice(0, row)
Demonstration
If you want repetitions in the subarrays and also expand your column number to the custom, independent from length of the original array number, you can use Array#repeated_combination
.
col
∈ [1; ∞3 )row
∈ [0;col
col
]:
days.repeated_combination(col).to_a.slice(0, row)
Demonstration
1 col
is the number of elements in each subarray.
2 row
is the number of subarrays in the desired 2D array.
3 The upper bound is specified as ∞ to represent that this value is not bounded by the length of the original array.
Is there a limit on the size of an array in ruby?
There is not a software limit imposed by Ruby, but there is a limit as to how much the process can support. If you have a regular home server running the Ruby server, it would be able to handle an array until the array became too large, at which point it would begin to 'bog down', lag, crash, etc. On the other hand, if you had an extremely powerful corporate server, it could handle a much larger array, but would still eventually crash/lag if the array became too large for the process and the hardware (memory) to handle.
I don't have any concrete numbers for you, because it all depends on the hardware and software on the server.
Inspect with limited recursion
No, you might want to use either prettyprint module for a 'different' visualisation (require 'pp'; pp object) or write something yourself. To write a generic dumper is quite difficult since everyone has different needs (dump binary blobs? dump strings up to which length? dump graphs with cycles? dump up to which level? ...).
Creating array of numbers from 0 to n for positive and negative n
To support negative numbers, you could use upto
and downto
along with a condition:
(I'm showing a stand-alone method here instead of patching Integer
)
def make_array(n)
if n > 0
0.upto(n).to_a
else
0.downto(n).to_a
end
end
The above creates an enumerator that's converted to an array using Enumerable#to_a
.
You might want to skip the intermediate object (the enumerator) by directly calling Array::new
- it creates an array with the given number of elements:
n = 3
Array.new(n) #=> [nil, nil, nil]
If a block is given, it passes each element's index to the block and we are supposed to returns its value. The index is in fact just what we want, so we can simply return it:
Array.new(n) { |i| i } #=> [0, 1, 2]
As you can see, Array.new(n)
returns n
elements, but we need n + 1
, so let's fix that:
Array.new(n + 1) { |i| i } #=> [0, 1, 2, 3]
Unfortunately, Array::new
doesn't accept a negative size:
Array.new(-3) #=> negative array size (ArgumentError)
So for negative n
we have to pass -n
and also return -i
:
n = -3
Array.new(-n + 1) { |i| -i } #=> [0, -1, -2, -3]
As a method:
def make_array(n)
if n > 0
Array.new(n + 1) { |i| i }
else
Array.new(-n + 1) { |i| -i }
end
end
Let's try to avoid the duplication.
Converting n
to a positive number is easy using abs
:
3.abs #=> 3
-3.abs #=> 3
Applied to our code:
n = 3
Array.new(n.abs + 1) { |i| i } #=> [0, 1, 2, 3]
n = -3
Array.new(n.abs + 1) { |i| i } #=> [0, 1, 2, 3]
For the block, we could use a ternary if
:
n = 3
Array.new(n.abs + 1) { |i| n > 0 ? i : -i } #=> [0, 1, 2, 3]
n = -3
Array.new(n.abs + 1) { |i| n > 0 ? i : -i } #=> [0, -1, -2, -3]
We can even remove the condition by using the spaceship operator a <=> b
. It determines whether a
is less than, equal to, or greater than b
by returning -1
, 0
or +1
, respectively.
More specifically, for Fixnum#<=>
, n <=> 0
returns 1
if n
is greater than 0
, and -1
if n
is less than 0
:
3 <=> 0 #=> 1
-3 <=> 0 #=> -1
We can use <=>
's result in our block to multiply i
with:
Array.new(n.abs + 1) { |i| i * (n <=> 0) }
This is equivalent to i * 1
(if n > 0
) or i * -1
(if n < 0
).
(There's a third return value: n <=> 0
returns 0
if n
is equal to 0
but that doesn't matter, because in that case the resulting array is [0]
and 0 * 0
is still 0
)
As a method:
def make_array(n)
Array.new(n.abs + 1) { |i| i * (n <=> 0) }
end
Although it is short, this method became quite complex and it's not obvious what is is doing. Therefore, I would prefer the first method (the one using upto
and downto
) because of its simplicity.
has_many through: how to retrieve the id of a line in the correspondance table?
OK, I am stupid...
i was focusing on the lines where i know that item.matrices[x] was not nil... and the error came from the lines where items.matrices[x] is nil...
So everything is solved by just adding a unless items.matrices[x].nil?
That's the fun thing about programming: wasting time for things like this... but learning anyway :)
Related Topics
How to Catch Top Level Failures on an Eventmachine Server
Case-Insensitive Find_Or_Create_By_Whatever
Testing Rake Tasks with Rspec Is Not Accepting Arguments
How to Create All Possible Combinations with Two Arrays
Actioncontroller::Routingerror (No Route Matches [Get] "/"):
Finding the Date for a Given Week Number
Why #!/Usr/Bin/Env Ruby Doesn't Work in Crontab
Autoload Paths and Nested Services Classes Crash in Ruby
Upgrade Ruby on Elastic Beanstalk
What Could Be Causing This Rails Ioerror Closed Stream
Why Does the Break Statement in Ruby Behave Differently When Using Proc.New V. the Ampersand Sign
How to Make a Ruby Enumerator That Does Lazy Iteration Through Two Other Enumerators
Ruby Getting the Longest Word of a Sentence
Ruby Instance_Eval on a Class with Attr_Accessor
Why Does 6.Times.Map Work in Ruby 1.8.7 But Not 1.8.6
Ruby on Rails - Activerecord::Relation Count Method Is Wrong