We have variable "a" and we want to create variable "b" as a mirror of "a" variable and then change one of its elements.
Code
function h(){
var a=[[1,2,3]]
var b=a;
b[0][0]="test"
Logger.log(b)
Logger.log(a)
}
Output
[[test,2,3]]
[[test,2,3]]
Why is this happening? Any way to avoid this?
This referes to another question:
Copying array by value in JavaScript
You may test some suggested solutions. I've tested this answer:
https://stackoverflow.com/a/23245968/5372400
The code:
function h(){
var a=[[1,2,3]];
var b = JSON.parse(JSON.stringify(a));
b[0][0]="test";
Logger.log(b);
Logger.log(a);
}
result is
[[test, 2, 3]]
[[1.0, 2.0, 3.0]
Looks like, javascript like c does not do array assignments.
You have to deep copy value in array b for this you can use slice method :
arr2 = arr1.slice();
Below is your code with some modifications:
function h(){
var a=[1,2,3];
var b= a.slice();
b[0]="test";
console.log(b);
console.log(a);
}
Related
I have been looking for a solution everywhere on the internet but nowhere I can see a single script which lets me read the name of a variable as a string in Godot 3.1
What I want to do:
Save path names as variables.
Compare the name of the path variable as a string to the value of another string and print the path value.
Eg -
var Apple = "mypath/folder/apple.png"
var myArray = ["Apple", "Pear"]
Function that compares the Variable name as String to the String -
if (myArray[myposition] == **the required function that outputs variable name as String**(Apple) :
print (Apple) #this prints out the path.
Thanks in advance!
I think your approach here might be a little oversimplified for what you're trying to accomplish. It basically seems to work out to if (array[apple]) == apple then apple, which doesn't really solve a programmatic problem. More complexity seems required.
First, you might have a function to return all of your icon names, something like this.
func get_avatar_names():
var avatar_names = []
var folder_path = "res://my/path"
var avatar_dir = Directory.new()
avatar_dir.open(folder_path)
avatar_dir.list_dir_begin(true, true)
while true:
var avatar_file = avatar_dir.get_next()
if avatar_file == "":
break
else:
var avatar_name = avatar_file.trim_suffix(".png")
avatar_names.append(avatar_name)
return avatar_names
Then something like this back in the main function, where you have your list of names you care about at the moment, and for each name, check the list of avatar names, and if you have a match, reconstruct the path and do other work:
var some_names = ["Jim","Apple","Sally"]
var avatar_names = get_avatar_names()
for name in some_names:
if avatar_names.has(name):
var img_path = "res://my/path/" + name + ".png"
# load images, additional work, etc...
That's the approach I would take here, hope this makes sense and helps.
I think the current answer is best for the approach you desire, but the performance is pretty bad with string comparisons.
I would suggest adding an enumeration for efficient comparisons. unfortunately Godot does enums differently then this, it seems like your position is an int so we can define a dictionary like this to search for the index and print it out with the int value.
var fruits = {0:"Apple",1:"Pear"}
func myfunc():
var myposition = 0
if fruits.has(myposition):
print(fruits[myposition])
output: Apple
If your position was string based then an enum could be used with slightly less typing and different considerations.
reference: https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_basics.html#enums
Can't you just use the str() function to convert any data type to stirng?
var = str(var)
I need to check if the certain value exists in both arrays and if exists remove this element from the second array. I know that it exists.
taking the 1st element from array doubleTue, taking the index where is this value in amTue and pmTue then remove those by using splice command.
But now my code is having problem on getting the first value.
tried as in level array: var val = doubleTue[i]
and 2 level array: var val - doubleTue[i][0]
tried toString(), read()
for (var n=0; n<doubleTue.length; n++)
{
var val = doubleTue[i][0];
var val1 = amTue.indexOf(val);
if (val1!=-1) {amTue.splice(val1, 1);};
var val2=pmTue.indexOf(val);
if (val2!=-1) {pmTue.splice(val2, 1); };
}
}
the issue is found. i have used wrong variable for looping. hehe. copy past issue
thnks all
In real project, TEST_TABLE would contain much of TEST_TABLE_NESTED, each with its own testVariable and bunch of testScript. test function from testScript would be used in C++ code, and TEST_TABLE_NESTED tables would be added automatically from C++ code too.
TEST_TABLE =
{
TEST_TABLE_NESTED =
{
testVariable = 5,
testScript =
{
test = function()
print(testVariable, "hello") --How to access 'testVariable'?
end
}
}
}
EDIT :
This is the actual scenario of using this script:
GameObjectScriptTables =
{
GameObject_1 = --Container of scripts corresponding to some gameObject
{
gameObjectOwner = actual_object_passed_from_c++, --This is an actual object passed from c++
GameObjectScript_1 = --This is a script with update(dt) method which will be called somwhere in c++ code
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
}
}
GameObject_2 =
{
gameObjectOwner = actual_object_passed_from_c++,
GameObjectScript_1 =
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
},
GameObjectScript_2 =
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
}
}
--And so on
}
Idea is that exists some testVariable object (passed from C++), which data is used all over TEST_TABLE_NESTED. For me, above example looks natural for this task, but it prints nil instead of 5. So how to acces a testVariable from testScript without printing a full path like TEST_TABLE.TEST_TABLE_NESTED.testVariable?
You're asking for something like a "parent" pointer, which tells table B about table A, but that doesn't exist. Internally, the only association they have is that one of A's values happens to be B, but any number of tables could contain B as a value. Which is B's parent?
If you want B to know about A, you'll need to tell it. You can add an extra parameter to update which receives the game owner object, or update can be a closure which contains the game owner as a bound variable, so on and so forth.
I made it work by providing a gameObjectOwner instance for each GameObjectScript_N. However I don't know is it expensive solution or not.
Is there an actionscript library providing a queuing system?
This system would have to allow me to pass the object, the function I want to invoke on it and the arguments, something like:
Queue.push(Object, function_to_invoke, array_of_arguments)
Alternatively, is it possible to (de-)serialize a function call? How would I evaluate the 'function_to_invoke' with the given arguments?
Thanks in advance for your help.
There's no specific queue or stack type data structure available in ActionScript 3.0 but you may be able to find a library (CasaLib perhaps) that provides something along those lines.
The following snippet should work for you but you should be aware that since it references the function name by string, you won't get any helpful compiler errors if the reference is incorrect.
The example makes use of the rest parameter which allows you to specify an array of arbitrary length as the arguments for your method.
function test(... args):void
{
trace(args);
}
var queue:Array = [];
queue.push({target: this, func: "test", args: [1, 2, "hello world"] });
queue.push({target: this, func: "test", args: ["apple", "pear", "hello world"] });
for (var i:int = 0; i < queue.length; i ++)
{
var queued:Object = queue[i];
queued.target[queued.func].apply(null, queued.args);
}
Sure, that works similar to JavaScript
const name:String = 'addChild'
, container:Sprite = new Sprite()
, method:Function = container.hasOwnProperty(name) ? container[name] : null
, child:Sprite = new Sprite();
if (method)
method.apply(this, [child]);
So a query method could look like:
function queryFor(name:String, scope:*, args:Array = null):void
{
const method:Function = scope && name && scope.hasOwnProperty(name) ? scope[name] : null
if (method)
method.apply(this, args);
}
I have a Java array such as:
String[] arr = new String[] {"123","doc","projectReport.doc"};
In my opinion the natural way to access would be:
#set($att_id = $arr[0])
#set($att_type = $arr[1])
#set($att_name = $arr[2])
But that it is not working. I have come with this workaround. But it a bit too much code for such an easy task.
#set($counter = 0)
#foreach($el in $arr)
#if($counter==0)
#set($att_id = $el)
#elseif($counter==1)
#set($att_type = $el)
#elseif($counter==2)
#set($att_name = $el)
#end
#set($counter = $counter + 1)
#end
Is there any other way?
You can use use Velocity 1.6: for an array named $array one can simply do $array.get($index).
In the upcoming Velocity 1.7, one will be able to do $array[$index] (as well as $list[$index] and $map[$key]).
You could wrap the array in a List using Arrays.asList(T... a). The new List object is backed by the original array so it doesn't wastefully allocate a copy. Even changes made to the new List will propagate back to the array.
Then you can use $list.get(int index) to get your objects out in Velocity.
If you need to get just one or two objects from an array, you can also use Array.get(Object array, int index)
to get an item from an array.
String[] arr = new String[] {"123", "doc", "projectReport.doc"};
In my opinion the natural way to access would be:
#set($att_id = $arr[0])
#set($att_type = $arr[1])
#set($att_name = $arr[2])
The value for this can be get by using $array.get("arr", 1) because there is no direct way to get the value from array like $att_id = $arr[0] in velocity.
Hope it works :)
Velocity 1.6
$myarray.isEmpty()
$myarray.size()
$myarray.get(2)
$myarray.set(1, 'test')
http://velocity.apache.org/engine/1.7/user-guide.html
there is an implicit counter $velocityCount which starts with value 1 so you do not have to create your own counter.
Brian's answer is indeed correct, although you might like to know that upcoming Velocity 1.6 has direct support for arrays; see the Velocity documentation for more information.
I ended up using the ListTool from the velocity-tools.jar. It has methods to access an array's elements and also get its size.
I has the same question and it got answered on another thread
#set ( $Page = $additionalParams.get('Page') )
#set ( $Pages = [] )
#if ( $Page != $null && $Page != "" )
#foreach($i in $Page.split(";"))
$Pages.add($i)
#end
#end
Array indexing in Confluence / Velocity templates