I get an unexpected result when I append a new object onto an array of objects. The append seems to overwrite the existing object in the array then append itself.
Any thoughts? Or am I missing something really simple.
Here's test code from my playground:
class myRecord {
var firstName: String?
var lastName: String?
}
var myRecords = [myRecord]()
var tempRecord = myRecord()
tempRecord.firstName = "John"
tempRecord.lastName = "Brown"
myRecords.append(tempRecord)
tempRecord.firstName = "Jane"
tempRecord.lastName = "Doe"
myRecords.append(tempRecord)
for x in 0..<myRecords.count {
print(x, "=", myRecords[x].firstName!, myRecords[x].lastName!) }
Console output:
0 = Jane Doe
1 = Jane Doe
This happens obviously because class are Reference Type. if your creating object of class that means your are creating memory reference of that class. And if you are changes property of that class that means your are changing the value of that reference in your memory heap. That why your last object (i.e Jane Doe) is replacing the value value of first Object(i.e John Brown).
So now in Array both elements refers same memory reference that why you getting both same object(i.e Jon Doe). If you changes implementation to struct, you getting answer as per you are implementing, Because struct are Value Type. So it refers only value of object.
To be more specify About class and struct Please read this link
Just replace 'class' with 'struct' as class are reference type and struct are value type.
struct myRecord {
var firstName: String?
var lastName: String?
}
var myRecords = [myRecord]()
var tempRecord = myRecord()
tempRecord.firstName = "John"
tempRecord.lastName = "Brown"
myRecords.append(tempRecord)
tempRecord.firstName = "Jane"
tempRecord.lastName = "Doe"
myRecords.append(tempRecord)
for x in 0..<myRecords.count {
print(x, "=", myRecords[x].firstName!, myRecords[x].lastName!) }
When you re-assigned the value of tempRecord.firstName and tempRecord.lastName, it overwrote the value at index 0 of the myRecords array to equal the new values you set.
Index 0 and Index 1 of the myRecords array both point to the same tempRecord class instance in memory which holds the value
{
firstName: Jane,
lastName: Doe
}
In order to add multiple instances of the myRecord class, you could create a separate instance called tempRecords1 and append the values to the myRecords array like so:
...
var tempRecord = myRecord()
var tempRecord1 = myRecord()
...
tempRecord1.firstName = "Jane"
tempRecord1.lastName = "Doe"
myRecords.append(tempRecord1)
just put after
tempRecord.firstName = "John"
tempRecord.lastName = "Brown"
myRecords.append(tempRecord)
tempRecord = myRecords ()
then add jane doe.
you can use Struct instead of Class, depends on what you need.
Related
What is the easiest way to search an ObjectArray in Kotlin by a property belonging to that Object?
For example I have a data class
data class Cat(
var name: String,
var age: Int,
var type: String,
)
and I have a Array<Cat> and would like to find the first occurrence of a cat with age == 4.
You can use find function to find the element with age == 4:
val cats = arrayOf(
Cat("Name1", 2, "Type1"),
Cat("Name2", 4, "Type2")
)
val cat: Cat? = cats.find { it.age == 4 }
find function returns the first element matching the given predicate, or null if no such element was found.
I have an array of type "User" and I'd like to delete all users that are 10 years old. My code :
struct User: Identifiable {
var id = UUID()
var name: String
var age: String
}
var array: User = [
User[name: "AZE", age: "10"]
User[name: "QSD", age: "37"]
]
What is the function for deleting an object from an element of that object? I hope you understood my problem and thank you for your answer.
You can use filter to keep only the elements of the array whose age property doesn't equal 10.
let filtered = array.filter { $0.age != "10" }
Unrelated to your question, but why is age a String? It should be an Int instead, since it represents a numeric value. Also, you should always make properties immutable (let) by default and only make them mutable (var) if they really need to be mutable.
I have a contoroller:
$scope.getFromDB=function(data)
{
$scope.nameSelected=[];
var myCookie=$cookie.get("nameCookie");
$scope.names= data;
for(var i=0; i<$scope.names.length;i++)
{
if($scope.names._id=myCookie._id)
{
$scope.nameSelected.push($scope.names[i]);
}
}
I want display the user's firstname, middlename, lastname stored in the $scope.nameSelected, since the nameSelectedis in the array form, name are got in array nameSelected[0].firstname, nameSelected[0].middlename,nameSelected[0].lastname. So how to convert it into a object so it is easy to access the names.
From what you've written,you don't need an array at all, just use an object.
Change this:
$scope.nameSelected=[];
...
$scope.nameSelected.push($scope.names[i]);
to
$scope.nameSelected = null;
...
$scope.nameSelected = $scope.names[i];
Based on what you've mentioned in your question, it is already an object at the index 0 of your nameselected array, That means, doing,
$scope.nameselected[0]
should give you this,
{firstName : "Robert", middlename :"Downy", lastName:"junior"}
Similarly, for all the names as in your loop ,
$scope.nameselected = $scope.names[i]
is it possible to have a dictionary, that contains multiple values for one key?
For example I have multiple IDs (101,102,103,104...) and all of those IDs have some values (colour: green, number: 4, city: New York). I am new to programming and not sure how should I store it.
I was thinking about custom class:
class myClass: NSObject {
var ID: Int
var colour: String
var number: Int
var city: String
init(ID: Int, colour: String, number: Int, city: String) {
self.ID = ID
self.colour = colour
self.number = number
self.city = city
}
}
And the create some variable var myData = myClass() and just everything there, but then how could I access lets say ID 102 and modify its colour?
So my question how to store data provided in my example with an option to be able select specific ID and modify values belonging to that ID.
A dictionary must contain exactly one value for each key. However, that value could be an array, or a dictionary, or an object etc. etc. so that is no practical restriction.
Since instance of classes are stored as references, the dictionary values could be references to class instances. So you can extract the reference to an instance from the dictionary, and then modify the instance. Be aware that anyone holding a reference to the same instance will see the same changes.
Assuming you have two instances of your class
let item101 = MyClass(ID: 101, colour: "red", number: 4, city: "NewYork")
let item102 = MyClass(ID: 102, colour: "green", number: 7, city: "Chicago")
You can store them in a dictionary using the ID as key
let dictionary = [101: item101, 102: item102]
and retrieve a value by ID with
if let id101 = dictionary[101] {
// use id101
} else {
print("ID 101 not found")
}
or you can use an array
let array = [item101, item102]
and get an item by ID with the filter function
let filtered = array.filter{ $0.ID == 102 }
if !filtered.isEmpty {
let id102 = filtered[0]
} else {
print("ID 102 not found")
}
Declare you id with Array and foreach in that ID
var ID: [Int]
I am not expert in Swift and I have been using it for few months to build Mac Apps. I would like to represent in memory a data structure like that of PHP associative arrays but in Swift. Let's imagine that I have a table of data to load in memory with the following fields/records:
ID Surname Name
1 XXX YYY
2 ZZZ WWW
3 JJJ KKK
What I would like to obtain is an associative array like the one I would be able to obtain in PHP:
$arr[1]["Surname"] = "XXX"
$arr[1]["Name"] = "YYY"
$arr[2]["Surname"] = "ZZZ"
$arr[2]["Name"] = "WWW"
I just cannot find the right data structure in Swift to obtain the same result. I tried with the following piece of code:
class resObject: NSObject {
private var cvs = [Int: [String: String]]()
override init() {
self.cvs[0] = ["Name" : "XXX"]
self.cvs[0] = ["Surname" : "YYY"]
self.cvs[1] = ["Name" : "ZZZ"]
self.cvs[1] = ["Surname" : "WWW"]
for (key, arr) in cvs {
let sur = arr["Surname"]
let nam = arr["Name"]
println("Row \(key) - Surname: \(sur), Name: \(nam)")
}
super.init()
}
}
It looks to me pretty close, but it does not work. What I get in the output is the following (I don't care about the "Optional(s)":
Row 0 - Surname: Optional("XXX"), Name: nil
Row 1 - Surname: Optional("ZZZ"), Name: nil
I tried to make some tests in debug and I noticed that the data that are saved in memory are just that of the last key:value pair used (i.e. if I assign Surname first and Name second I get Surname as nil and Name with the correct value).
Please consider that, as in the example, I don't know the data structure when I declare the variable, so I declare it empty and fill it programmatically later.
I don't know if it is just me not declaring the data structure correctly, or if it is Swift that does not allow to do that. Any help will be greatly appreciated.
Thanks a lot.
Regards,
Alessio
One way is a Dictionary of structs. Consider:
struct Person {
var firstName: String
var lastName: String
}
var peopleByID = [ Int: Person ]()
peopleByID[1] = Person(firstName: "First", lastName: "Last")
peopleByID[27] = Person(firstName: "Another", lastName: "LastName")
var myID = 1 // Try changing this to 2 later
if let p = peopleByID[myID] {
println("Found: \(p.firstName) with ID: \(myID)")
}
else {
println("No one found with ID: \(myID)")
}
You can then update the structure:
peopleByID[1].firstName = "XXX"
peopleByID[27].lastName = "ZZZ"
You can iterate freely:
for p in peopleByID.keys {
println("Key: \(p) value: \(peopleByID[p]!.firstName)")
}
Note that a mere array of [Person] isn't so hot, because the IDs:
-- may not be Ints, but are often Strings
-- even if they remain Ints, an array takes up storage in proportion to the highest numbered index, whereas a Dictionary only takes up storage in proportion to the number of stored objects. Imagine storing just two ID's: 523123, and 2467411.
EDIT
It seems like you don't know the attributes ahead of time that will go into each Person object. That's odd, but you should then do:
struct Person {
var attributes = [String : String]() // A dictionary of String keys and String values
}
var peopleByID = [ Int : Person ]()
// and then:
var p1 = Person()
var p2 = Person()
p1.attributes["Surname"] = "Somename"
p1.attributes["Name"] = "Firstname"
p2.attributes["Address"] = "123 Main St."
peopleByID[1] = p1
peopleByID[2] = p2
if let person1 = peopleByID[1] {
println(person1.attributes["Surname"]!)
for attrKey in person1.attributes.keys {
println("Key: \(attrKey) value: \(person1.attributes[attrKey]!)")
}
}