Array, Object, Memory. Actionscript - arrays

I have a question related to memory. I will give an example to make it clear how everything works now.
I have 2 arrays:
var ArrayNew:Array = new Array();
var ArrayOld:Array = new Array();
Also i have a class to store my objects (3 properties). For example:
public Id {get; set;}
public Name {get; set;}
public Type {get; set;}
The thing is, that i'm filling the ArrayNew with new objects every (for example 12 hours):
ArrayNew.push(x, x, x)
.....
ArrayNew.push(x, x, x)
It may be about ~200 records or even more.
After that i make this:
ArrayOld = ArrayNew;
ArrayNew = null;
So the thing is, how memory works in this situation and what happens with objects? Does ArrayOld = ArrayNew make a copy of objects (cause now it works)? Does ArrayNew=null delete created objects?
I wish you undearstand the situation. :)

The objects stored in arrayOld get garbage collected if there are no other references to them. The ones from arrayNew are not copied - they are referenced by arrayOld after the assignment.
It's to say that that after:
arrayNew[0].name = 'a random silly text';
arrayOld = arrayNew;
arrayOld[0].name = 'another silly string';
trace(arrayNew[0]);
You'd get:
another silly string
Style note: Normally you don't start variable/object names with capitals, it's reserved for classes.

If I understand you correctly you want to know what happened to ArrayOld.
My code:
var arr_1:Array = ["Hello world!"];
var arr_2:Array = ["My name is Stas!"];
arr_2 = arr_1;
arr_1 = null;
trace(arr_2);// Hello world!
If I made a mistake with the understanding of the issue do explain it properly.

ArrayOld = ArrayNew is simply making ArrayOld reference the same thing as ArrayNew at that point. The actual data in memory is not copied.
ArrayNew = null is simply assigning null value to the ArrayNew reference. It doesn't delete the data ArrayNew previously referenced, nor does it affect other references to that data (such as ArrayOld).
At this point, the original data that ArrayNew used to reference has not changed in any way, you've just handed off what variable refers to it.
At this point if you did ArrayOld = null, then the original data in memory no longer has any reference to it and it will eventually be purged by garbage collection, but not right away. It will happen "later" at a time the runtime decides is convenient.

Related

SWIFT: assigning all values of an item in a structure array to a variable

Sorry, I don't even have an idea of the keywords to search for answer.
I want to store all items within a global structure to a local variable.
struct HighScores: Codable {
var highscoreRecord: [HighscoreRecord]
}
struct HighscoreRecord: Codable {
var Rank:Int
var Date:Date
var avDuration:Float
var Score:Int
}
A global variable is based on this structure and populated within a UIViewController
var jsonResult: HighScores?
Now, in another UIViewController, I want to extract the values of Score for all Highscores and store it to a local variable. I thought it should look somewhat like this, however, I do not get it to work
#IBDesignable class ScoreTimeGraphView: UIView {
var graphScore = jsonResult!.highscoreRecord.Score
The declaration above throws "Value of type '[HighscoreRecord]' has no member 'Score'"
Any ideas how to do this?
Cheers!
highscoreRecord is an Array. You can't use .Score directly on it because the Array type doesn't have a property named Score.
However, because it's element type is HighScore (which does have the property you want), you can iterate over it and collect the Score property from each one.
I think this is what you are after:
var allGraphScores = jsonResult!.highscoreRecord.map { $0.Score }
.map(_:) takes a closure with one parameter, and passes in each element of a sequence in turn.
So, highscoreRecord.map { $0.Score } returns a new array, by finding the Score property of each HighScoreRecord in the array highscoreRecord.
PS it's probably a good idea to name your variables using lowercase camelCase, for readability and instant recognition by any Swift dev that Score is a variable and not an object.
You're trying to access the property from an array. You need to provide an index to remove the error. Update this line:
var graphScore = jsonResult!.highscoreRecord.Score
To this:
var graphScore = jsonResult!.highscoreRecord[0].Score

How do I encode an array of Byte32 values for Web3j to pass to my smart contract?

Contract function is defined as:
function createAggregate (string memory key, bytes32[2] memory part_array) public returns (bytes32)
and have incoming a list of parts, defined as...
List<Bytes32> elements
so was trying to use:
List<Type> items = new ArrayList<Type>();
items.add(...); // user reference
items.add(new DynamicArray<>(elements));
final Function function = new Function("createAggregate",
items,
Arrays.asList(new TypeReference<Bytes32>() {})
);
...
But this does not work, seems to be an encoding issue - what is the right what of encoding the Bytes32 ? (This seems to work fine for an array of strings)
Sort of solved this with the following (although was really looking for a more dynamic size solution)
new StaticArray2(Bytes32.class, Utils.typeMap(elements, Bytes32.class));

Ordering when using scala.collection.Searching

I have an Array of [Long, Q] and would like to make a binary search on it. I tried below :
import scala.collection.Searching._
class Q (val b:Double, val a:Double)
val myArray = Array(5L -> new Q(1,2), 6L-> new Q(6,9), 7L-> new Q(7,6))
val i = myArray.search(6L).insertionPoint
but had this error
No implicit Ordering defined for Any
Unspecified value parameter ord.
I understand that I need to specify an odering rule for this collection Array[(Long,Q)] but can't figure this out myself.
Please help
Signature of search is search[B >: A](elem: B)(implicit ord: Ordering[B]). You've got an array of type [Long, Q]. So in order for the compiler to infer Ordering correctly, you'd have to invoke search like that:
myArray.search(6L-> q/*Q(6,9)*/)(Ordering.by(_._1)) //ordering by the first value in a tuple.
and what you're doing is: myArray.search(6L). If I understand correctly what you're trying to do, it's probably to find both value and position in the array.
You could solve it by using two separate data structures:
keys could be stored in the array, like this:
val myArray = Array(5L, 6L, 7L).toList
myArray.search(6L).insertionPoint
and if you'd need values, you could use map which would work as a dictionary:
val dictionary = Map(
5L -> new Q(1,2),
6L-> new Q(6,9),
7L-> new Q(7,6)
)
EDIT:
Actually, I noticed something like that would work:
val dummy = new Q(0,0) //any instance of Q
myArray.search(6L-> dummy)(Ordering.by(_._1)).insertionPoint //1
It works since for lookup of the insertion point Ordering is used and no equality test is performed.

Modifying an array of dictionaries in Swift

I’m new to Swift and have been having some troubles figuring out some aspects of Arrays and Dictionaries.
I have an array of dictionaries, for which I have used Type Aliases - e.g.
typealias myDicts = Dictionary<String, Double>
var myArray : [myDicts] = [
["id":0,
"lat”:55.555555,
"lng”:-55.555555,
"distance":0],
["id":1,
"lat": 44.444444,
"lng”:-44.444444,
"distance":0]
]
I then want to iterate through the dictionaries in the array and change the “distance” key value. I did it like this:
for dict:myDicts in myArray {
dict["distance"] = 5
}
Or even specifically making sure 5 is a double with many different approaches including e.g.
for dict:myDicts in myArray {
let numberFive : Double = 5
dict["distance"] = numberFive
}
All my attempts cause an error:
#lvalue $T5' is not identical to '(String, Double)
It seems to be acting as if the Dictionaries inside were immutable “let” rather than “var”. So I randomly tried this:
for (var dict:myDicts) in myArray {
dict["distance"] = 5
}
This removes the error and the key is indeed assigned 5 within the for loop, but this doesn't seem to actually modify the array itself in the long run. What am I doing wrong?
The implicitly declared variable in a for-in loop in Swift is constant by default (let), that's why you can't modify it directly in the loop.
The for-in documentation has this:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
In the example above, index is a constant whose value is automatically
set at the start of each iteration of the loop. As such, it does not
have to be declared before it is used. It is implicitly declared
simply by its inclusion in the loop declaration, without the need for
a let declaration keyword.
As you've discovered, you can make it a variable by explicitly declaring it with var. However, in this case, you're trying to modify a dictionary which is a struct and, therefore, a value type and it is copied on assignment. When you do dict["distance"] = 5 you're actually modifying a copy of the dictionary and not the original stored in the array.
You can still modify the dictionary in the array, you just have to do it directly by looping over the array by index:
for index in 0..<myArray.count {
myArray[index]["distance"] = 5
}
This way, you're sure to by modifying the original dictionary instead of a copy of it.
That being said, #matt's suggestion to use a custom class is usually the best route to take.
You're not doing anything wrong. That's how Swift works. You have two options:
Use NSMutableDictionary rather than a Swift dictionary.
Use a custom class instead of a dictionary. In a way this is a better solution anyway because it's what you should have been doing all along in a situation where all the dictionaries have the same structure.
The "custom class" I'm talking about would be a mere "value class", a bundle of properties. This was kind of a pain to make in Objective-C, but in Swift it's trivial, so I now do this a lot. The thing is that you can stick the class definition for your custom class anywhere; it doesn't need a file of its own, and of course in Swift you don't have the interface/implementation foo to grapple with, let alone memory management and other stuff. So this is just a few lines of code that you can stick right in with the code you've already got.
Here's an example from my own code:
class Model {
var task : NSURLSessionTask!
var im : UIImage!
var text : String!
var picurl : String!
}
We then have an array of Model and away we go.
So, in your example:
class MyDict : NSObject {
var id = 0.0
var lat = 0.0
var lng = 0.0
var distance = 0.0
}
var myArray = [MyDict]()
let d1 = MyDict()
d1.id = 0
d1.lat = 55.55
d1.lng = -55.55
d1.distance = 0
let d2 = MyDict()
d2.id = 0
d2.lat = 44.44
d2.lng = -44.44
d2.distance = 0
myArray = [d1,d2]
// now we come to the actual heart of the matter
for d in myArray {
d.distance = 5
}
println(myArray[0].distance) // it worked
println(myArray[1].distance) // it worked
Yes, the dictionary retrieved in the loop is immutable, hence you cannot change.
I'm afraid your last attempt just creates a mutable copy of it.
One possible workaround is to use NSMutableDictionary:
typealias myDicts = NSMutableDictionary
Have a class wrapper for the Swift dictionary or array.
class MyDictionary: NSObject {
var data : Dictionary<String,Any>!
init(_ data: Dictionary<String,Any>) {
self.data = data
}}
MyDictionary.data

as3 check for 2 objects with same property in array

I have an array, lets call it _persons.
I am populating this array with Value Objects, lets call this object PersonVO
Each PersonVO has a name and a score property.
What I am trying to do is search the array &
//PSEUDO CODE
1 Find any VO's with same name (there should only be at most 2)
2 Do a comparison of the score propertys
3 Keep ONLY the VO with the higher score, and delete remove the other from the _persons array.
I'm having trouble with the code implementation. Any AS3 wizards able to help?
You'd better use a Dictionary for this task, since you have a designated unique property to query. A dictionary approach is viable in case you only have one key property, in your case name, and you need to have only one object to have this property at any given time. An example:
var highscores:Dictionary;
// load it somehow
function addHighscore(name:String,score:Number):Boolean {
// returns true if this score is bigger than what was stored, aka personal best
var prevScore:Number=highscores[name];
if (isNaN(prevScore) || (prevScore<score)) {
// either no score, or less score - write a new value
highscores[name]=score;
return true;
}
// else don't write, the new score is less than what's stored
return false;
}
The dictionary in this example uses passed strings as name property, that is the "primary key" here, thus all records should have unique name part, passed into the function. The score is the value part of stored record. You can store more than one property in the dictionary as value, you'll need to wrap then into an Object in this case.
you want to loop though the array and check if there are any two people with the same name.
I have another solution that may help, if not please do say.
childrenOnStage = this.numChildren;
var aPerson:array = new array;
for (var c:int = 0; c < childrenOnStage; c++)
{
if (getChildAt(c).name == "person1")
{
aPerson:array =(getChildAt(c);
}
}
Then trace the array,

Resources