How do I use .fill method to create new objects? - arrays

Specifically, I'm wondering why when I create a new array with several sub-arrays using .fill, the sub-arrays created using .fill are the same object.
array = Array.new.fill([], 0..8)
subsquare[0].object_id => 7220340
subsquare[1].object_id => 7220340
How would I create these sub-arrays while ensuring each sub-array was its own object?

The why to this question can be found if you look at Array.new:
http://ruby-doc.org/core-2.2.0/Array.html
Note that the second argument populates the array with references to
the same object. Therefore, it is only recommended in cases when you
need to instantiate arrays with natively immutable objects such as
Symbols, numbers, true or false.
To create an array with separate objects a block can be passed
instead. This method is safe to use with mutable objects such as
hashes, strings or other arrays
The workaround as specified in the doc is:
array = Array.new(8) { [] }

Related

Is there a runtime difference in getting a length of primitive (string, number) type array vs. custom object type array?

In javascript, does getting a length of a number type array vs. custom object type array take the same time?
First array has elements of type number. Second has custom type something like this but not limited to:
ISomeType: {
e1: string,
e2: ISomeOtherType,
..
e16: number
}
Thanks a lot
This is more a JavaScript question than a TypeScript question, since it's about runtime behavior.
No, there's no difference in the speed of reading the length property. It's just a property of the array object (an "own" property, not inherited), exactly the same in both cases.
Slightly tangential, but: Setting the length of an array could theoretically have surprising time characteristics. Array objects are "exotic" objects (ones that don't behave like normal objects) and one of the ways they're exotic is that although length is defined as a data property (not an accessor property with getter and setter methods), setting it has a side effect: If you set it so that some elements in the array will no longer be in the array, the properties for those elements are removed. Here's an example:
const a = ["a", "b", "c"];
console.log(a.length); // 3
console.log(a[2]); // c
a.length = 1; // Removes the "b" and "c" elements
console.log(a.length); // 1
console.log(a[2]); // undefined
In theory, then, if you have a really, really big array (say, millions of elements) and you set length such that you're removing a lot of elements from the array, you'd see a larger delay than if you did that with a small array where you were removing only a few elements. But you'd have to have a truly massive array, and JavaScript engines could optimize the process (for instance, not really removing the properties, but instead checking later on retrieval whether they should still exist).

Array manipulation with nested arrays

let names = ['Ayomide',['Tolu',['Tola',['Chuka',['Dan']]]]];
How can I manipulate each element in this nested array. It's all index 0 and 1. Trying to figure out how to loop through this to get the elements individually, thanks
You could use name.flat(Infinity) to flatten it to a single array (Infinity tells it to go as deep as necessary), and then you can just use .forEach or whatever
let names = ['Ayomide',['Tolu',['Tola',['Chuka',['Dan']]]]];
console.log(names.flat(Infinity))

Why does Range#select produce an Array object?

Consider I have a Range object,
(1..30).class # => Range
Now consider I am trying to find the factors of num,
num = 30
factors = (1..num).select { |n| num % n == 0 }
factors.class # => Array
For Ruby 2.3.1 a Range object does not have #select, but an Array object does. How is calling Range#select producing an Array object?
I believe that I am not fully understanding the Ruby Object Model. My current understanding is that factors.class.eql? Range should return true, not false.
factors.class.eql? Array # => true
The object model in Ruby is simple, single inheritance but with ability to "mixin" modules to add shared behavior. In your case you are using the select method which exists in the module Enumerable. This module is mixed into Array, Hash, and Range. This gives instances of those classes methods such as select. You can read more about enumerable methods here: https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-select
If you think about it, it makes sense that Range#select returns an Array. You're not selecting contiguous values from the range are you? You're selecting arbitrary values from which the block returns true, this makes it impossible to return a range therefore, #select will always return an array even if it's called on a Hash or any other Class that mixes in Enumerable.
Update:
To understand how Enumerable is returning an Array from a Range
To implement any classes that mix in Enumerable you only have to define the #each method on your class. Say you hypothetically re-implemented Range:
class Range
include Enumerable # mixin
def initialize(first, last)
#number_range = first.upto last # this is an array of ints
end
def each(&block) # this methods returns an enumerable
#number_range.each &block
end
end
With the above we can initialize our hypothetical range instance:
#hypo_range = Range.new 1, 10
And call enumerable methods on it:
#hypo_range.any? { |i| i == 5 } # => true
#hypo_range.select &:odd? # => [1,3,5,7,9]
Because you need only implement #each to hook into the Enumerable API, Ruby knows exactly what to do with it no matter what the class of the object is. This is because in your new #each method you are iterating over an array already! Enumerable uses your each method under the hood to implement all the other enumerable methods on top e.g. any?, select, find, etc.
That #each method is where you tell Ruby how to iterate over your collection of objects. Once Ruby knows how to iterate over your objects the results are already an Array.
Rubinius implementation of Range
You can see here that Range is implemented by using while to loop from the first value until it reaches the last value and yielding to the block on each iteration. The block collects the results into an Array and that's how you get the Array out of calling Range#select because select is using that each under the hood.
https://github.com/rubinius/rubinius/blob/master/core/range.rb#L118
Some resources:
https://www.sitepoint.com/guide-ruby-collections-iii-enumerable-enumerator/
https://mauricio.github.io/2015/01/12/implementing-enumerable-in-ruby.html
http://practicingruby.com/articles/building-enumerable-and-enumerator
Check the docs for Range http://ruby-doc.org/core-2.3.1/Range.html
It says included modules Enumerable. And that's where there are implemented map, all?, any?, find, select, inject and many many more methods.

In order to preallocate memory in Matlab, I want to initialize my array of objects. How do I do this?

I have a class of objects known as blocks. Currently, I am creating an array of blocks using a for loop by simply tacking them unto an empty array
blockArray=[];
for ii=1:Size
blockArray=[blockArray block(....)];
end
In order to preallocate memory, how do I initialize an object array of blocks with dummy values?
For instance if instead of using block objects I used numbers, I could easily preallocate by using zeros(1,Size). Is there something similar that I could do?
The matlab documentation describes
To preallocate the object array, assign the last element of the array first. MATLABĀ® fills the first to penultimate array elements with default DocArrayExample objects.
So, to do this, instead of iterating over from 1:size, it is simpler to do...
blockArray = []
blockArray(size) = block(...)
The language does not really support this, there exists multiple solutions (or workarounds).
Replicating the first instance
When pushing the first element into the array, you can fill the whole array with this element to achieve a preallocation. This might look very bad, but it is actually the fastest possibility known to me.
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
if ii==1
%to do preallocation, fill it with your first element
blockArray(1:S)=e
else
blockArray(ii)=e
end
end
Use cell arrays
Obvious simple solution, you can put any class into the fields
blockArray=cell(S,1);
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
blockArray{ii}=e
end
This solution is very simple but slower than the first. You also lose some functionality which is not available for cell arras
Let your class implement array functionality
classdef A
properties
arg1
out
end
methods
function obj = A(varargin)
if nargin==0
%null object constructor
elseif strcmpi(varargin{1},'createarray')
sz=varargin(2:end);
%preallocate
obj(sz{:})=A;
else
%standard constructor
obj.arg1=varargin{1};
obj.out=[1 2 3;];
end
end
end
end
Constructor with no input argument creates an "empty" or "null" object, this is used to preallocate so it should be empty.
Constructor with first parameter makearray creates an array
Otherwise your constructor should be called.
Usage:
%create an empty object
A
%create an array of size 2,3,4
A('createarray',2,3,4)
%use the standard constructor
A(2)
Biggest downside is you have to modify your classes. Never tested this solution, but it should be close to the first in performance.

Converting between an ActionScript Array (Object[]) and a Vector.<Object>

Are there options for converting an Array to a Vector in ActionScript without iterating the array?
What about the other way (converting a Vector to an Array)?
For the Array to Vector, use the Vector.<TYPE>() function that accept an array and will return the vector created :
var aObjects:Array = [{a:'1'}, {b:'2'}, {c:'3'}];
// use Vector function
var vObjects:Vector.<Object> = Vector.<Object>(aObjects);
For the other there is no builtin function, so you have to do a loop over each Vector item and put then into an Array
vObjects.push.apply(null, aObjects);
And another way to do it.
The trick here is simple. If you try to use the concat() method to load your array into a vector it will fail because the input is a vector and instead of adding the vector elements AS will add the whole vector as one entry. And if you were to use push() you'd have to go through all items in the array and add them one by one.
In ActionScript every function can be called in three ways:
Normal way: vObjects.push(aObjects)
Throws error because aObjects is not an Object but an Array.
The call method: vObjects.push.call(this, myObject1, myObject2, ..., myObjectN)
Doesn't help us because we cannot split the aObjects array into a comma-separated list that we can pass to the function.
The apply method: vObjects.push.apply(this, aObjects)
Going this route AS will happily accept the array as input and add its elements to the vector. You will still get a runtime error if the element types of the array and the vector do not match. Note the first parameter: it defines what is scoped to this when running the function, in most cases null will be fine, but if you use the this keyword in the function to call you should pass something other than null.
var myArray:Array = [].concat(myVector);
might work.

Resources