How does one alter self in an Array to be a totally new array? How do I fill in the commented portion below?
class Array
def change_self
#make this array be `[5,5,5]`
end
end
I understand this: Why can't I change the value of self? and know I can't just assign self to a new object. When I do:
arr = [1,2,3,4,5]
arr contains a reference to an Array object. I can add a method to Array class that alters an array, something like:
self[0] = 100
but is it possible to change the length of the array referenced by arr?
How are these values stored in the Array object?
You are asking three very different questions in your title and in your text:
Is it possible to alter an Array object's length using an Array method?
Yes, there are 20 methods which can (potentially) change the length of an Array:
<< increases the length by 1
[]= can alter the length arbitrarily, depending on arguments
clear sets the length to 0
compact! can decrease the length, depending on contents
concat can increase the length, depending on arguments
delete can decrease the length, depending on arguments and contents
delete_at can decrease the length, depending on arguments
delete_if / reject! can decrease the length, depending on arguments and contents
fill can increase the length, depending on arguments
insert increases the length
keep_if / select! can decrease the length, depending on arguments and contents
pop decreases the length
push increases the length
replace can alter the length arbitrarily, depending on arguments and contents (it simply replaces the Array completely with a different Array)
shift decreases the length
slice! decreases the length
uniq! can decrease the length, depending on contents
unshift increases the length
When monkey patching the Array class, how does one alter "self" to be a totally new array? How do I fill in the commented portion below?
class Array
def change_self
#make this array be [5,5,5] no matter what
end
end
class Array
def change_self
replace([5, 5, 5])
end
end
How are these values actually stored in the Array object?
We don't know. The Ruby Language Specification does not prescribe any particular storage mechanism or implementation strategy. Implementors are free to implement Arrays any way they like, as long as they obey the contracts of the Array methods.
As an example, here's the Array implementation in Rubinius, which I find fairly readable (at least more so than YARV):
vm/builtin/array.cpp: certain core methods and data structures
kernel/bootstrap/array.rb: a minimal implementation for bootstrapping the Rubinius kernel
kernel/common/array.rb: the bulk of the implementation
For comparison, here is Topaz's implementation:
lib-topaz/array.rb
And JRuby:
core/src/main/java/org/jruby/RubyArray.java
arr = [1,2,3,4,5]
arr.replace([5,5,5])
I wouldn't monkey-patch a new method into Array; especially since it already exists. Array#replace
As Array are mutables, you can alter it's contents:
class Array
def change_self
self.clear
self.concat [5, 5, 5]
end
end
You modify the array so it becomes empty, and then add all the elements from the target array. They still are two different objects (ie, myAry.object_id would differ from [5, 5, 5].object_id), but now they are equivalent arrays.
Moreover, the array still is the same that before - just it's content changed:
myAry = [1, 2, 3]
otherRef = myAry
previousId = myAry.object_id
previousHash = myAry.hash
myAry.change_self
puts "myAry is now #{myAry}"
puts "Hash changed from #{previousHash} to #{myAry.hash}"
puts "ID #{previousId} remained as #{myAry.object_id}, as it's still the same instance"
puts "otherRef points to the same instance - it shows the changes, too: #{otherRef}"
Anyway, I really don't know why one would want to do this - are you solving the right problem, or just kidding with the language?
Related
I'm trying to make a function in Scala that when -
println(thisIsAFunction(Array(1,1,4,5,4,4)))
is called, it will give me a new array that is always half the size of the array input (the array input will always be an even number and bigger than 2), and in the new array it will not contain the same number twice. So for example, in the above statement, it would return an array consisting of the numbers 1, 4 and 5. I have been trying to approach this a number of ways but can't get my head round it.
def thisIsAFunction(a: Array[Int]) =
a.distinct.take(a.length/2)
The distinct method removes any duplicates from the Array so that it does not contain the same number twice.
The take methods reads the first n elements of the result, so take(a.length/2) gives an Array that is half the length of the original.
Basically, I’m given a list of strings such as:
["structA.structB.myArr[6].myVar",
"structB.myArr1[4].myArr2[2].myVar",
"structC.myArr1[3][4].myVar",
"structA.myArr1[4]",
"structA.myVar"]
These strings are describing variables/arrays from multiple structs. The integers in the arrays describe the size each array. Given a string has a/multiple arrays (1d or 2d), I want to generate a list of strings which go through each index combination in the array for that string. I thought of using for loops but issue is I don’t know how many arrays are in a given string before running the script. So I couldn’t do something like
for i in range (0, idx1):
for j in range (0, idx2):
for k in range (0, idx3):
arr.append(“structA.myArr1[%i][%i].myArr[%i]” %(idx1,idx2,idx3))
but the issue is that I don’t know how I can create multiple/dynamic for loops based on how many indexes and how I could create a dynamic append statement that changes per each string from the original list since each string will have a different number of indexes and the arrays will be in different locations of the string.
I was able to write a regex to find all the index for each string in my list of strings:
indexArr = re.findall('\[(.*?)\]', myString)
//after looping, indexArr = [['6'],['4','2'],['3','4'],['4']]
however I'm really stuck on how to achieve the "dynamic for loops" or use recursion for this. I want to get my ending list of strings to look like:
[
["structA.structB.myArr[0].myVar",
"structA.structB.myArr[1].myVar",
...
"structA.structB.myArr[5].myVar”],
[“structB.myArr1[0].myArr2[0].myVar",
"structB.myArr1[0].myArr2[1].myVar",
"structB.myArr1[1].myArr2[0].myVar",
…
"structB.myArr1[3].myArr2[1].myVar”],
[“structC.myArr1[0][0].myVar",
"structC.myArr1[0][1].myVar",
…
"structC.myArr1[2][3].myVar”],
[“structA.myArr1[0]”,
…
"structA.myArr1[3]”],
[“structA.myVar”] //this will only contain 1 string since there were no arrays
]
I am really stuck on this, any help is appreciated. Thank you so much.
The key is to use itertools.product to generate all possible combinations of a set of ranges and substitute them as array indices of an appropriately constructed string template.
import itertools
import re
def expand(code):
p = re.compile('\[(.*?)\]')
ranges = [range(int(s)) for s in p.findall(code)]
template = p.sub("[{}]", code)
result = [template.format(*s) for s in itertools.product(*ranges)]
return result
The result of expand("structA.structB.myArr[6].myVar") is
['structA.structB.myArr[0].myVar',
'structA.structB.myArr[1].myVar',
'structA.structB.myArr[2].myVar',
'structA.structB.myArr[3].myVar',
'structA.structB.myArr[4].myVar',
'structA.structB.myArr[5].myVar']
and expand("structB.myArr1[4].myArr2[2].myVar") is
['structB.myArr1[0].myArr2[0].myVar',
'structB.myArr1[0].myArr2[1].myVar',
'structB.myArr1[1].myArr2[0].myVar',
'structB.myArr1[1].myArr2[1].myVar',
'structB.myArr1[2].myArr2[0].myVar',
'structB.myArr1[2].myArr2[1].myVar',
'structB.myArr1[3].myArr2[0].myVar',
'structB.myArr1[3].myArr2[1].myVar']
and the corner case expand("structA.myVar") naturally works to produce
['structA.myVar']
So I have several arrays of positions, velocities, etc in 3D-space (vec3(x,y,z)) and another array which holds indices that are used to look-up in the vec3 arrays. This is all for a particle-system representing cloth (in case anyone was wondering).
The second array is far larger than the position array because for each particle, the second array represents a type of "spring" relationship with another particle. So for example, any given particle might have a "spring" attached to 3 different particles. So the first bunch of indices in the second array might look like this: [0, 1, 0, 2, 0, 3, 0, 4, ...]
The problem here is that the position array is sorted based on a hash function used for finding neighbors in a uniform grid. This means that the indices held in the 2nd array will no longer be valid. I'm trying to figure out a way to sort the positions and then still use the 2nd array to index properly.
One thought that I've had would be to have a 3rd array which stores the new indices based on the sorting function, but I am not sure how I could actually go about doing this.
Also, the reason the data is separated rather than being put into an object is that this is being run in CUDA and it is an optimization for speed/memory.
Is there a simple way of going about this? Thanks for any help.
Would something like this work?
Transfer your array of vec3(x, y, z)s into an array of pair(index, vec3(x, y, z)). Sort this new array by taking the hash function of the second element. The result will be a sorted array of pair(index, vec3(x, y, z)), where index is the vector's initial position in the array. Then, use this to construct a third "lookup" array of integers whose indices are the initial indices and whose values are the new values. Now to get a vector from your second array you do something like vector_pairs[lookup[spring[4]]].second.
Python-ish pseudocode:
vecs = ...
spring = ...
pair_vecs = [(index, vec) for index, vec in enumerate(vecs)]
pair_vecs.sort(key=lambda index, vec: hash(vec))
lookup = [0] * len(pair_vecs)
for new_index, (initial_index, vec) in enumerate(pair_vecs):
lookup[initial_index] = new_index
In my program I need to work with arrays roughly 500x500 to 1500x1500 within a function that is looped over 1000's of times. In each iteration, I need to start with an array that has the same form (whose dimensions are fixed across all iterations). The initial values will be:
[0 0 0 ... 1]
[0 0 0 ... 1]
....
However, the contents of the array will be modified within the loop. What is the most efficient way to "reset" the array to this format so I can pass the same array to the function every time without having to allocate a new set of memory every time? (I know the range of rows that were modified)
I have tried:
a[first_row_modified:last_row_modified,:] = 0.
a[first_row_modified:last_row_modified,:-1] = 1.
but it takes roughly the same amount of time as just creating a new array every time with the following:
a = zeros((sizeArray, sizeArray))
a[:,-1] = 1.
Is there a faster way to effectively "erase" the array and change the last column to ones? I think this is similar to this question, clearing elements of numpy array , although my array doesn't change sizes and i didn't see the definitive answer to the previously asked question.
No; I think the way you are doing it is about as fast as it gets.
I am currently trying to figure out how to design some sort of loop to insert data into an array sequentially. I'm using Javascript in the Unity3D engine.
Basically, I want to store a bunch of coordinate locations in an array. Whenever the user clicks the screen, my script will grab the coordinate location. The problem is, I'm unsure about how to insert this into an array.
How would I check the array's index to make sure if array[0] is taken, then use array[1]? Maybe some sort of For loop or counter?
Thanks
To just add onto the end of an array, just use .push().
var myArray = [];
var coord1 = [12,59];
var coord2 = [87,23];
myArray.push(coord1);
myArray.push(coord2);
myArray, now contains two items (each which is an array of two coordinates).
Now, you wouldn't do it this way if you were just statically declaring everything as I've done here (you could just statically declare the whole array), but I just whipped up this sample to show you how push works to add an item onto the end of an array.
See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push for some reference doc on push.
In case you need to know the array's length when reading the array in the future, you can use the .length attribute.
var lengthOfArray = myArray.length;
Using the .push() method as suggested by jfriend00 is my recommendation too, but to answer your question about how to work out what the next index is you can use the array's length property. Because JavaScript arrays are zero-based The length property will return an integer one higher than the current highest index, so length will also be the index value to use if you want to add another item at the end:
anArray[anArray.length] = someValue; // add to end of array
To get the last element in the array you of course say anArray[anArray.length-1].
Note that for most purposes length will give the number of elements in the array, but I said "one higher than the current highest index" above because JavaScript arrays are quite happy for you to skip indexes:
var myArray = [];
myArray[0] = "something";
myArray[1] = "something else";
myArray[50] = "something else again";
alert(myArray.length); // gives '51'
// accessing any unused indexes will return undefined