Swift 4 append items to a specific section in a structured array - arrays

I am looking to (per this example) add more items to a specific section of a structured array after creating the initial entry.
struct Zoo {
let section: String
let items: [String]
}
var objects = [Zoo]()
let animals = Zoo(section: "Animals", items: ["Cat","Dog","Mouse"])
let birds = Zoo(section: "Birds", items: ["Crow","Pidgeon","Hawk"])
let reptiles = ["Snake","Lizard"]
objects.append(animals)
objects.append(birds)
// ... varous logic and proccessing where I determine I need
// to add two more items to the animals section...
// trying to extend animals with two more entries.
// this is where I am getting hung up:
objects[0].items.append(reptiles)

Remove the following code
objects[0].items.append(reptiles)
Use this code:
objects[0].items += reptiles
Update for Swift 5:
In Swift 5, this solution will not work and you will get an error like
"Left side of mutating operator isn't mutable: 'items' is a 'let'
constant"
The solution is to change the structure :
struct Zoo {
let section: String
var items: [String]
}

Related

I want to filter array

I got two arrays from API call,
One is nameArray - which contains recipe names ( menuNameArray = ["pohe","bread","cheese chilli toast"]
And another array - which contains prices of those recipes (menuPriceArray = ["10", "40", "120"].
I have got theses two arrays from API call.
I am displaying both the arrays on the table view & I am searching through the menuNamesArray because I want to search by recipe names.
I am getting recipe names by searching those from menuNameArray. Now I want menuPriceArray to get updated also according to searched menuName Array.
means if I search for "bread" then I must get price value as "40" and accordingly for other names also.
How should I perform such filtering on the second array?
My code Snippet -
//MARK: UISearch result update delegate
func updateSearchResults(for searchController: UISearchController) {
// here arrFilter is the resulting array to sotre searched items from menuNamesArray
arrFilter.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (menuNamesArray as NSArray).filtered(using: searchPredicate)
let result = menuPriceArray.firstIndex(of: array.startIndex)
arrFilter = array as! [String]
self.tblSearch.reloadData()
//here now I got the searched menu names, Now I want prices for searched menu names from menuPrice Array..
}
Never use multiple arrays as data source.
Swift is an object oriented language. Take advantage of it.
Create a struct
struct Menu {
let name : String
let price : Double
}
and a data source array
var menues = [Menu]()
Filter the array by name and get the price, pretty easy and straightforward
if let foundMenu = menues.filter(where: {$0.name == "bread"}) {
print(foundMenu.price)
}
You can merge the two arrays into one array of dictionary elements.

Check if struct string array contains elements of another string array

I created an array of struct elements. These structs get to contain an array of strings. I want to check if these strings happen to be in another array of strings.
How can I do that or what tools should I look into?
I found that I can use a command called "Set", but it doesn't seem to work arrays within a struct.
import UIKit
// Define structure
struct Drink {
var name: String
var content: Array<String>
var amount: Array<Int>
var desc: String
}
// Define drinks
var mojito = Drink(name: "Mojito", content: ["Rum","Club soda"], amount: [4,20], desc: "Summer drink")
var vodkaJuice = Drink(name: "Vodka juice", content: ["Vodka","Juice"], amount: [4,20], desc: "Cheap alcohol")
var list = [mojito,vodkaJuice]
// Define what ingredients you have
var stock = ["Gin", "Vodka", "Juice", "Club soda"]
How do I make a list of drinks I can make from what I have?
Use a Set instead of an array so you can simply do a subset check:
import UIKit
// Define structure
struct drink {
var name : String
var content : Set<String> // we use a Set instead
var amount : Array<Int>
var desc : String
}
// Define drinks
var mojito = drink(name: "Mojito", content: ["Rum","Club soda"], amount: [4,20], desc: "Summer drink")
var vodkaJuice = drink(name: "Vodka juice", content: ["Vodka","Juice"], amount: [4,20], desc: "Cheap alcohol")
var list = [mojito,vodkaJuice]
// Define what ingredients you have
var stock = ["Gin", "Vodka", "Juice", "Club soda"]
// find all instances of drinks where their contents
// are subsets of what you have in stock
let drinks = list.filter { $0.content.isSubset(of: stock) }
The importance of using sets instead of "for-loops inside for-loops" is performance. Set uses an internal hash table to look up an item in an extremely fast fashion. So the overall complexity of your lookups would be O(N.logM) for N items in list and M items in stock.
If you had done it with for loops, its complexity would be O(N.M) which could take longer and consume more battery depending on the number of items you have.
That doesn't mean you should always use sets though. Sets have tradeoffs. They bring in performance but their initial construction is slower and they don't support duplicate items. Use them only in specific cases like this. Never use sets because "they are faster", use them when they solve your specific problem.
I strongly recommend skimming over those additional data structures provided by Swift's runtime so you'll know which one to use and when.

Create ordered Array from Dictionary

This is a fundamental thing that I should know but don't know at a deep level and therefore find confusing. Dictionaries seem to be unordered list of keys and values. I want to create an ordered list of keys and values so that I can sort and otherwise keep track of order. I think this means I have to convert the dictionary into a multi-dimensional Array that has the key and value and also an index value ie 0,1,2,3 etc.
If my dictionary looks like the following:
var myScores = [String: Float]()
myScores = ["player1":22,"player2":33]
How do I convert it into an Array where player1:22 is the first element and player2:33 is the second element?
Edit:
Alternative without creating struct is to create an empty array of dictionaries in the form of your dictionary and then append your dictionary to the array.
var myArray = [[String: Float]]()//note double brackets
propArray.append(myScores)
What you want is an array of structs.
struct Score {
let playerName: String
let score: Int
}
let scores = [Score(playerName: "player1", score: 22),
Score(playerName: "player2", score: 33),
]
let sortedScores = scores.sorted(by: { $0.playerName < $1.playerName })
To get key-value pairs out of a dictionary is straightforward, though it forces you to work with tuples, which are not a particularly friendly type. Even so, it's done this way:
let sortedScores = myScores.sorted { $0.key < $1.key }
That will create:
[(key: "player1", value: 22.0), (key: "player2", value: 33.0)]
Or
for (name, score) in myScores.sorted(by: { $0.key < $1.key }) {
print(name, score)
}
You can keep the dictionary as-is. One possible solution is to create an array that contains just the keys in the desired order. Then you can iterate the key array and access the elements of the dictionary.
var myScores: [String:Float] = ["player1":22, "player2":33]
var myPlayers = myScores.keys.sorted()
for player in myPlayers {
let score = myScores[player]
}
This works when you want to show the data in some particular order, such as in a table view.

Swift picker array error

var pickerData: [[String]] = [String]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Connect data:
self.gothramPicker.delegate = self
self.gothramPicker.dataSource = self
pickerData = [
[["A"],["i","ii","iii"]],
[["B"],["iv","v","vi","vii"]]
]"
getting error of Contextual type 'String' cannot be used with array literal. 
my picker has two sections and each item if selected in the first picker has its own subdivisions to select from the second picker.
I want to use Array in Array and each main array has subarrays of different list. When I select first array in the picker it should show only the subitems of the particular Array item. For which when I add the double Brackets, I am getting the error. Also please let me know any error in the code
#sureshtrb , I am not posting answer because you don't asked question here. Frankly, you are troubling in Syntax understanding only.
You were declaring picketData of type Array([]) that contains array of string[[String]], and by putting ["A"] in place of string, you are adding an array ["A"] in place of String "A".
As per your real problem, I suggest you to go with 2 diff array or use dictionary.
The below code compiles.
var pickerData: [[String]] = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
pickerData = [
["A","i","ii","iii"],
["B","iv","v","vi","vii"]
]
}

Swift: Accessing array value in array of dictionaries

I am currently struggling with obtaining a value from an array inside an array of dictionaries. Basically I want to grab the first "[0]" from an array stored inside an array of dictionaries. This is basically what I have:
var array = [[String:Any]]()
var hobbies:[String] = []
var dict = [String:Any]()
viewDidLoad Code:
dict["Name"] = "Andreas"
hobbies.append("Football", "Programming")
dict["Hobbies"] = hobbies
array.append(dict)
/// - However, I can only display the name, with the following code:
var name = array[0]["Name"] as! String
But I want to be able to display the first value in the array stored with the name, as well. How is this possible?
And yes; I know there's other options for this approach, but these values are coming from Firebase (child paths) - but I just need to find a way to display the array inside the array of dictionaries.
Thanks in advance.
If you know "Hobbies" is a valid key and its dictionary value is an array of String, then you can directly access the first item in that array with:
let hobby = (array[0]["Hobbies"] as! [String])[0]
but this will crash if "Hobbies" isn't a valid key or if the value isn't [String].
A safer way to access the array would be:
if let hobbies = array[0]["Hobbies"] as? [String] {
print(hobbies[0])
}
If you use a model class/struct things get easier
Given this model struct
struct Person {
let name: String
var hobbies: [String]
}
And this dictionary
var persons = [String:Person]()
This is how you put a person into the dictionary
let andreas = Person(name: "Andreas", hobbies: ["Football", "Programming"])
persons[andreas.name] = Andreas
And this is how you do retrieve it
let aPerson = persons["Andreas"]

Resources