This question already has answers here:
How can I run through three separate arrays in the same for loop?
(6 answers)
Closed 4 years ago.
I would like to end up with an array of custom objects. I'm having trouble figuring out a way to go about this when I have multiple arrays to iterate through in order to create the custom objects. I have something like this:
class CustomObject {
var name = ""
var place = ""
var price = ""
}
var nameArray = [“name1”,"name2","name3"]
var placeArray = [“place1”,"place2","place3"]
var priceArray [“price1”,"price2","price3"]
var customArray [CustomObject]()
createObject(name : nameArray, place : placeArray, price : priceArray)
func createObject(name : [String], place : [String], price : [String]) {
let instance = CustomObject()
for names in name {
instance.name = names
}
for places in place {
instance.place = places
}
for prices in price {
instance.price = prices
customArray.append(instance)
}
}
I would like to end up with an array of those custom "instances". Right now my code is giving each attribute the last index of each array.
You can try , also i suppose all the arrays have the same count
var customArray = [CustomObject]()
for i in 0..<nameArray.count {
let instance = CustomObject()
instance.name = nameArray[i]
instance.place = placeArray[i]
instance.price = priceArray[i]
customArray.append(instance)
}
Related
I have my code below and I am attempting to create new arrays, in which the numbers in the elements increment by 1 whenever the user adds a book. For instance, when the user already has 1 book added and when he adds another one the array should read as ["bookTitle2,"bookAuthor2", "bookPublisher2", "bookNumOfPages2"]
let bookDetails = ["bookTitle", "bookAuthor", "bookPublisher", "bookNumOfPages"]
var bookDetail = ""
var bookNumber = Int()
var bookNumArray = [Int]()
if bookNumArray.contains(bookNumber) {
print("Book already exists")
} else {
while bookNumber < 2 {
bookNumber += 1
bookNumArray.append(bookNumber)
for detail in bookDetails {
bookDetail = "\(detail)" + String(bookNumber)
let newBookArray = [bookDetail]
print(newBookArray)
}
}
}
When I run the code above, this shows up instead:
["bookTitle1"]
["bookAuthor1"]
["bookPublisher1"]
["bookNumOfPages1"]
["bookTitle2"]
["bookAuthor2"]
["bookPublisher2"]
["bookNumOfPages2"]
So I want all the strings that end with 1 in one array and those that end in 2 in another array.
When you do:
for detail in bookDetails {
bookDetail = "\(detail)" + String(bookNumber)
let newBookArray = [bookDetail]
print(newBookArray)
}
For every iteration you are creating a new array with the current detail e.g bookTitle into an array of your string var bookDetail declared outside of this loop's scope.
Also note that newBookArray is a local variable, so it will be destroyed when it gets out of the loop. You would need an array of bookDetail to store the newBookArray.
let bookDetails = ["bookTitle", "bookAuthor", "bookPublisher", "bookNumOfPages"]
var bookDetailArray : [Array<String>] = [] //Your array to store all the bookDetails
var bookDetail : [String] = [] //Your array to store a bookDetail
var bookNumber = Int()
var bookNumArray = [Int]()
Then you can do:
bookDetail.removeAll() //Clear all objects before appending new one
for detail in bookDetails {
bookDetail.append("\(detail) + String(bookNumber)")
}
bookDetailArray.append(bookDetail)
Just a suggestion: As other people said, a dictionary or a class for the bookDetail properties would be a better model in your case. Read up on Object-oriented programming if you ever plan to use a class.
I would do a dictionary or create a class bookDetails with properties like bookTitle, bookAuthor, etc. And then I would create an array of the instances of this class.
If you want to do it your way, Why not create a two-way array, something like:
var arrayFinal = [[""]]
var bookNumber = 0
// Whenever the action is triggered
bookNumber += 1
var bookDetails = ["bookTitle", "bookAuthor", "bookPublisher", "bookNumOfPages"]
for detail in bookDetails
{
detail = "\(detail) +\(bookNumber)"
}
arrayFinal.add(bookDetails)
Or something like that...
I have an array like:-
var arrayData : Array<Dictionary<String, [BottleModel]>> = []
Bottle model :-
class BottleModel: NSObject {
var name : String
var price : Int
var reviews : Int
var category : String
var quantity : String
var id : String
var shopData : ShopModel
}
I want filtered array where price is > 2000
I tried let searchByInts = arrayData.filter({m in m.price < 200})
but getting below error:
Contextual closure
type '(Dictionary) -> Bool' expects 1 argument,
but 0 were used in closure body
How to filter such kind of array based on price
Working code:
let searchByInts = arrayData.filter { $0.values.contains { $0.contains { $0.price > 2000 } } }
By the way please write the following using literals:
var arrayData : [[String : [BottleModel]]] = []
Still no idea if that is what you actually want because your goal is very unclear. You have an array of dictionaries of arrays which actually contain the values you want to filter out. If a BottleModel costs more than 2000 do you want to keep the entire array it is contained in and the dictionary that array is in? You might want to map the entire data into one flat array before or after filtering.
Alternative using flatMap:
let flat = arrayData.flatMap { $0.values.flatMap { $0 } }
let searchByInts2 = flat.filter { $0.price < 200 } // or some other criteria
I'm new in swift and I'd know how to do that in php, but I'm lost with all those dictionaries and I have no idea how to do that in swift 2. I've been googling for a while and didn't found what I need.
I'm parsing a jSon and storing it's values in an NSMutableDictionary in a loop and at the end of the loop I store the NSMutableDictionary in an NSMutableArray, so at the end I have an NSMutableArray with 43 elements, and each element have about 10 keys with their values. I need to sort those 43 elements from their "distance" key and sort them descending. I don't know if that is posible with this current approach. The value of the key "distance" is an int number (meters). I don't know if to use an NSMutableDictionary inside an NSMutable Array is the correct approach to do this but I'm using it because it is possible to have string keys, and not numbers indexes, so for me it's easier to access the key "distance" than the index 8...
First I load the jSon content:
private func parseJson(json : NSMutableArray, tableView : UITableView){
var c : Int = 0
for j in json {
var jsonValues = NSMutableDictionary()
//Create main value
guard let value = j.valueForKey("value")?.valueForKey("value")! else{
continue
}
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
continue
}
jsonValues["name"] = Name
//more code like this....
TableData.append(Name)
nsDict.insertObject(jsonValues, atIndex: c)
c += 1
}
this is my NSMutableArray content after being loaded:
And this is the code I have this far. Im trying to load the sorted content in a new array, but in this new array some keys are missing.
//Reorder Array by shop distance from user...
var sortDescriptor:NSSortDescriptor = NSSortDescriptor(key: "distance", ascending: true)
var sortedArray : NSArray = nsDict.sortedArrayUsingDescriptors([sortDescriptor])//Crashes
print(sortedArray)
I've managed to sort the array with this technique:
created a new class with for my array
import Foundation
class JsonArrayValues {
init(){
}
var name = String()
var distance = Float()
var lat = Float()
var lng = Float()
var openingTime = String()
var country = String()
var code = String()
var address = String()
var categories = String()
var city = String()
var type = String()
var brands = String()
}
I instantiated one before the loop:
var jsonArrData : [JsonArrayValues] = []
And another one inside the loop, in which I've added the values:
var c : Int = 0
for j in json {
var jsonValues : JsonArrayValues = JsonArrayValues()
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
continue
}
jsonValues.name = Name
//more code...
jsonArrData.append(jsonValues)
c += 1
}
And finally I've been able to call the function to reorder the array:
//Reorder Array by shop distance from user...
jsonArrData.sortInPlace({$0.distance < $1.distance})
One of your first steps in any non-trivial project really should be to spend some time looking around on github for tools that simplify your problem. In this case, you'd find there are so very many tools to simplify working with JSON in Swift. I'd suggest you look at EVReflection and Gloss particularly, although there are also many people who use SwiftyJSON.
You don't mention how you're accessing the network; you could look at AFNetworking or Alamofire. The latter also has AlamofireJsonToObjects to help.
I also found JSONExport to be incredibly useful.
You'd be spending a lot less time futzing with details as in this unfortunate question and more getting on with your larger goal.
I have an array of type "drugList", and they are derived from a struct "DrugsLibrary":
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["": [""," "]]
My data model is initialized using this function:
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
self.drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
self.drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
self.drugList.append(drug3)
}
my problem is that i'm trying to create a dictionary from the drugList where the key is the drugSubCategory and the value is the drug name. The value should be an array if there are several drugs in this subcategory
for example, the dictionary should look something like this for this example:
dictionary = [
"Penicillins": ["drug1","drug2"]
"Macrolides": ["drug3"]
]
I tried this method:
for item in drugList {
dictionary["\(item.drugSubCategory)"] = ["\(item.drugName)"]
}
this gave a dictionary like this, and it couldn't append drug2 to "Penicllins":
dictionary = [
"Penicillins": ["drug1"]
"Macrolides": ["drug3"]
]
So I tried to append the items into the dictionary using this method but it didn't append anything because there were no common items with the key "" in the data model:
for item in drugList {
names1[item1.drugSubCategory]?.append(item1.drugName)
}
Anyone knows a way to append drug2 to the dictionary?
I would appreciate any help or suggestion in this matter.
You need to create a new array containing the contents of the previous array plus the new item or a new array plus the new item, and assign this to your dictionary:
for item in drugList {
dictionary[item.drugSubCategory] = dictionary[item.drugSubCategory] ?? [] + [item.drugName]
}
You can use .map and .filter and Set to your advantage here. First you want an array of dictionary keys, but no duplicates (so use a set)
let categories = Set(drugList.map{$0.drugSubCategory})
Then you want to iterate over the unique categories and find every drug in that category and extract its name:
for category in categories {
let filteredByCategory = drugList.filter {$0.drugSubCategory == category}
let extractDrugNames = filteredByCategory.map{$0.drugName}
dictionary[category] = extractDrugNames
}
Removing the for loop, if more Swifty-ness is desired, is left as an exercise to the reader ;).
I have two unrelated observations:
1) Not sure if you meant it as an example or not, but you've initialized dictionary with empty strings. You'll have to remove those in the future unless you want an empty strings entry. You're better off initializing an empty dictionary with the correct types:
var dictionary = [String:[String]]()
2) You don't need to use self. to access an instance variable. Your code is simple enough that it's very obvious what the scope of dictionary is (see this great writeup on self from a Programmers's stack exchange post.
Copy this in your Playground, might help you understand the Dictionaries better:
import UIKit
var str = "Hello, playground"
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["":""]
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
drugList.append(drug3)
}
createDrugsList()
print(drugList)
func addItemsToDict() {
for i in drugList {
dictionary["item \(i.drugSubCategory)"] = "\(i.drugName)"
}
}
addItemsToDict()
print(dictionary)
This question already has answers here:
How to find index of list item in Swift?
(23 answers)
Closed 7 years ago.
Here is my code in Swift for an iOS app.
class Test {
var name: String
var sname: String
init(name: String, sname: String) {
self.name = name
self.sname = sname
}
}
class ArrTest {
var arr = [Test]()
init() {
arr.append(Test(name: "test1", sname: "surname1"))
arr.append(Test(name: "test2", sname: "surname2"))
arr.append(Test(name: "test3", sname: "surname3"))
arr.append(Test(name: "test4", sname: "surname4"))
}
}
var x = ArrTest()
let obj = x.arr.filter { $0.name == "test1" }.first
println(obj?.sname)
I want to get the index and not the object of the first array object (in the array var). The "obj" x.arr.filter... returns the first object. I need the index of the correct object.
Well you can simply use the method find of the array:
// This is pseudocode haven't tried it but should go along those lines.
var x = ArrTest()
var searchMe = Test("test1", "surname1");
let obj = find(x, searchMe);
For this to work you need to implement the Equatable protocol, here you can find a simple tutorial. After that find should work with your test class.
let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d")