How to update merged array after one is being updated in Swift - arrays

In the following example, how can I make mix to update to reflect changes made to any of the merged arrays?
var fruits = ["Apple", "Orange", "Bannana"]
var cars = ["Cobalt", "Durango", "Jetta"]
var mix = fruits + cars
print(fruits)
print(cars)
print(mix)
cars.append("Mustang") // cars array modification
print(mix) // how to update mix to show Mustang?

Computed variable is what are you looking for, I believe:
var fruits = ["Apple", "Orange", "Bannana"]
var cars = ["Cobalt", "Durango", "Jetta"]
var mix: [String] {return fruits + cars}
print(mix)
//["Apple", "Orange", "Bannana", "Cobalt", "Durango", "Jetta"]
cars.append("Mustang") // cars array modification
print(mix)
//["Apple", "Orange", "Bannana", "Cobalt", "Durango", "Jetta", "Mustang"]

This would be the simplest way (perhaps not the most efficient)...
var fruits = ["Apple", "Orange", "Bannana"]
var cars = ["Cobalt", "Durango", "Jetta"]
var mix = fruits + cars
print(fruits)
print(cars)
print(mix)
cars.append("Mustang") // cars array modification
mix = fruits + cars
print(mix) // Now shows Mustang.
mix does not contain a reference back to cars so you can't expect it to be dynamically updated when cars is updated.

Related

How can I add text to a label from two different arrays in swift chosen at Random

I have created a label with a frame on the screen which displays the chosen text. I also have two different arrays for the first and last name.
let nameArray = ["Jacob", "Lenny", "George", "Linda", "Arthur"]
let lastNameArray = ["Shelby", "Knight", "Luiz", "Hamilton", "Dobson"]
when I use nameLabel.text = nameArray.randomElement() it works fine, but I want it to display both a random first name and a random last name from the given arrays within the same label. How would I go about doing this?
Just do the same thing but twice
nameLabel.text = "\(nameArray.randomElement()!) \(lastNameArray.randomElement()!)"
You can zip both array and then use random.
Here is solution
let nameArray = ["Jacob", "Lenny", "George", "Linda", "Arthur"]
let lastNameArray = ["Shelby", "Knight", "Luiz", "Hamilton", "Dobson"]
let combine = Array(zip(nameArray, lastNameArray))
let randomName = combine.randomElement() ?? ("", "")
nameLabel.text = randomName.0 + " " + randomName.1
I recommend this way, randomPerson even creates (5) unique full names and starts over when all names are expended.
let firstNames = ["Jacob", "Lenny", "George", "Linda", "Arthur"]
let lastNames = ["Shelby", "Knight", "Luiz", "Hamilton", "Dobson"]
var tempFirstNames = [String]()
var tempLastNames = [String]()
func randomPerson() -> String {
if tempLastNames.isEmpty {
tempLastNames = lastNames
tempFirstNames = firstNames
}
let firstName = tempFirstNames.remove(at: Int.random(in: 0..<tempFirstNames.count))
let lastName = tempLastNames.remove(at: Int.random(in: 0..<tempLastNames.count))
return "\(firstName) \(lastName)"
}
And use it
nameLabel.text = randomPerson()

Creating array in Swift

I'm using Swift to create an array that needs to match this format:
let items = [["1", "red", "33", "canada"], ["2", "blue", "66", "usa"]]
In my code, I query a database and have multiple rows returned with the pertinent info:
let items = [id+" - "+colour+" - "+number+" - "+home_location]
I use a loop to .append the array but the format comes out like this instead:
["1 - red - 33 - canada", "2 - blue - 66 - usa"]
What do I need to do to create the required array structure?
For each row of the database, instead of
let items = [id+" - "+colour+" - "+number+" - "+home_location]
say
let items = [id, colour, number, home_location]
Now append that to a var array of [[String]].
create model for your data like this
class ModelClass {
var id = ""
var colour = ""
var number = ""
var home_location = ""
}
and then create the object of your model class like this
let objmodel : ModelClass = ModelClass()
objmodel.id = "1"
objmodel.colour = "red"
objmodel.number = "33"
objmodel.home_location = "canada"
then create your main array and append this model object to your model array
var arrData = [ModelClass]()
arrData.append(objmodel)

Swift3 iOS -Firebase How to Separate Node Data Into Different Arrays and Dictionaries

root
|
#-clothing
|
#-nameBrandRalphLauren//topLevel
| |
| #-apparelTops//child
| | |-"garmetSweater":"white"
| | |-"garmetTshirt":"blue"
| | |-"postedBy":"user123"
| |
| #-apparelBottoms//child
| |-"garmetShorts":"tan"
| |-"garmetJeans":"blue"
| |-"postedBy":"user123"
|
#-nameBrandNike//topLevel
|
#-apparelTops//child
|-"garmetSweater":"gray"
|-"garmetTshirt":"pink"
|-"postedBy":"user789"
I have several top level nodes in Firebase that also have child nodes underneath them. Inside the child nodes are the keys and values. I want to separate each topLevelNode (RalphLauren,Nike) into an array that contains it's child nodes (apparelTops, apparelBottoms) and then put them inside their own arrays.
How would I achieve something like this
var nameBrandNodes = [String]()
var apparelNodes = [[String]]()
var garmetNodes = [[String:Any]]()
nameBrandNodes = [RaplhLaurn, Nike]
apparelNodes = [[apparelTops, apparelBottoms], [apparelTops, apparelBottoms]]
garmetNodes = [["postedBy":"user123"], ["garmetSweater":"white"],["garmetTshirt":"blue"],["garmetShorts":"tan"], ["garmetJeans":"blue"], ["postedBy":"user789"], ["garmetSweater":"gray"], ["garmetTshirt":"pink"]]
//**EDIT** Jay's answer is CORRECT. I forgot to add this and added it after he answered
var nameBrandArrayOfDict = [[String:[String]]]
nameBrandArrayOfDict = [[nameBrandRalphLauren:[apparelTops,apparelBottoms], [[nameBrandNike:[apparelTops,apparelBottoms]]
//this is only necessary because sometimes there won't be an apparelBottomsNode or apparelTopsNode for e.g.
nameBrandArrayOfDict = [[nameBrandRalphLauren:[apparelTops], [[nameBrandNike:[apparelBottoms]]
Here is the code:
let rootRef = Database.database().reference()
var nameBrandNodes = [String]()
var apparelNodes = [[String]]()
var garmetNodes = [[String:Any]]()
let clothingRef = rootRef.child("clothing")
clothingRef?.observe(.childAdded, with: {
(snapshot) in
//nameBrandNodes now contains RalphLauren and Nike
self.nameBrandNodes.append(snapshot.key)
for nameBrand in self.nameBrandNodes{
let apparel = rootRef.child("clothing").child("nameBrand")
apparel.observeSingleEvent(of: .value, with: {
(snapshot) in
for child in snapshot.children {
//what should I do in here?
}
}
My end result is I'm using a vertical tableView and a horizontal collectionsView. I'm going to list the nameBrands inside the tableView, the apparel inside the collectionView, and the the garment items inside the collectionViews cells. I know how to put everything into the tableView and collectionView once it's separated, the problem I'm having is separating everything into different arrays.
I am going to throw down this answer as it addresses the question and may provide some direction and other options.
In this code we are populating a ClothingClass which contains the data that matches the data in Firebase. We also have two arrays bottomsArray and topsArray that keeps those items in separate arrays (per the question).
The concept here is that everything in Firebase is snapshot, and snapshots can contain other snapshots (i.e. a dictionary can contain other dictionaries).
We read in the entire node by .value and each high level node (the name brand) is the key to those nodes (the key in the key:value pair). The value on the other hand is also a snapshot i.e.
let apparelBottomsSnap = nameBrandSnap.childSnapshot(forPath: "apparelBottoms")
Once we have those snapshots, assign their values to dictionaries and from there add the the ClothingClass as well as the separate array. There is no correlation between the ClothingClass and the arrays other than using the class is another way to organize the data in code for this example.
class ClothingClass {
var nameBrand = ""
var bottomsDict = [String: Any]()
var topsDict = [String: Any]()
}
var bottomsArray = [[String: Any]]()
var topsArray = [[String: Any]]()
var clothingArray = [ClothingClass]()
let clothingRef = self.ref.child("clothing")
clothingRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let nameBrandSnap = child as! DataSnapshot //this is each name_brand
let apparelBottomsSnap = nameBrandSnap.childSnapshot(forPath: "apparelBottoms")
let apparelTopsSnap = nameBrandSnap.childSnapshot(forPath: "apparelTops")
let bottomsDict = apparelBottomsSnap.value as! [String: Any]
let topsDict = apparelTopsSnap.value as! [String: Any]
let aClothing = ClothingClass()
aClothing.nameBrand = nameBrandSnap.key
aClothing.bottomsDict = bottomsDict
aClothing.topsDict = topsDict
clothingArray.append(aClothing)
bottomsArray.append(bottomsDict)
topsArray.append(topsDict)
}
//for testing
for c in clothingArray {
let n = c.nameBrand
let b = c.bottomsDict
let t = c.topsDict
print("n: \(n)")
print(" b: \(b)")
print(" t: \(t)")
}
print(topsArray)
print(bottomsArray)
})
The test loop at end end iterates over the array full of clothing classes and prints the properties of each one
n: name_brand_0
b: ["garmetJeans": Blue, "garmetShorts": Pink, "postedBy": user_2]
t: ["garmetShirt": blue, "garmetSweater": blue, "postedBy": user_0]
n: name_brand_1
b: ["garmetJeans": Orange, "garmetShorts": Navy, "postedBy": user_3]
t: ["garmetShirt": Green, "garmetSweater": Yellow, "postedBy": user_1]
and the print statement following prints the tops
[
["garmetShirt": blue, "garmetSweater": blue, "postedBy": user_0],
["garmetShirt": Green, "garmetSweater": Yellow, "postedBy": user_1]
]
and the bottoms
[
["garmetJeans": Blue, "garmetShorts": Pink, "postedBy": user_2],
["garmetJeans": Orange, "garmetShorts": Navy, "postedBy": user_3]
]

Is there an equivalent of JavaScript's indexOf for Rust arrays?

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var index = fruits.indexOf("Apple");
let fruits = ["Banana", "Orange", "Apple", "Mango"];
let index = fruits.???
If there is no equivalent, maybe you can point me in the right direction? I found this example, but it's for vectors, not arrays.
You can use the method position on any iterator. You can get an iterator over an array with the iter() method. Try it like this:
let fruits = ["Banana", "Orange", "Apple", "Mango"];
let res1 = fruits.iter().position(|&s| s == "Apple");
let res2 = fruits.iter().position(|&s| s == "Peter");
println!("{:?}", res1); // outputs: Some(2)
println!("{:?}", res2); // outputs: None

Swift 2 How to create a random dictionary from 2 similar arrays

I'm using xcode 7, and I am wondering how to create a randomized dictionary from two similar arrays.
For example
var array1 = ["apple", "banana", "orange", "strawberry", "cherry"]
var array2 = ["apple", "banana", "orange", "strawberry", "cherry"]
I then want the code to create a random dictionary like so:
var dict = ["apple": "banana", "banana": "apple", "orange": "cherry", "strawberry": "orange", "cherry": "strawberry"]
Also, I don't want to have both value and key to be the same, ie no "apple": "apple".
I'm relatively new to coding. Any help would be greatly appreciated :)
You can use shuffle function from Nate Cook's answer to shuffle values array and then simply fill dictionary with keys and values:
var keys = ["apple", "banana", "orange", "strawberry", "cherry"]
var values = keys
values.shuffle()
var d = [String: String]()
for (index, item) in keys.enumerate() {
d[item] = values[index]
}
The advantage of this solution that it's O(n) (execution time and consumed memory linearly depends from number of items).
Your particular example is a bit contrived as there is really no point in dealing with two identical arrays, you can simply use one. I guess something like this should do the trick:
var fruits = ["apple", "banana", "orange", "strawberry", "cherry"]
var dict = [String: String]()
for (keyIndex, key) in fruits.enumerate() {
var valueIndex: Int {
var index: Int
repeat {
index = Int(arc4random_uniform(UInt32(fruits.count)))
} while index == keyIndex || dict.values.contains(fruits[index])
return index
}
dict[key] = fruits[valueIndex]
}

Resources