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)
Related
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()
In my first vc (ViewController) I have button with action performSegue. In override func prepare(for segue:) I want to send data to another view controller.
This is my code:
if segue.identifier == "nextVC" {
let data1 = ["TITLE", "TITLE2"]
let data2 = ["DESCRIPTION", "DESCRIPTION 2", "DESCRIPTION 3"]
let destination = segue.destination as! DestinationController
destination.cellString1 = data1
destination.cellString2 = data2
destination.array = array
In my second vc (DestinationController) I have variable cellString1, cellString2 and array like below:
var array: [String] = []
var cellString1: [String] = []
var cellString2: [String] = []
In array I send to second vc id of tableView cell in first vc like below:
["0", "1", "1", "0", "1"]
In second vc I have tableView too with code (in tableview(cellForRowAt:))like below:
if array[indexPath.row] == "0" {
cell.textLabel?.text = cellString1[indexPath.row]
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 16)
cell.backgroundColor = UIColor.black
return cell
} else if array[indexPath.row] == "1" {
cell2.textLabel?.text = cellString2[indexPath.row]
cell2.textLabel?.textColor = UIColor.gray
cell2.textLabel?.font = UIFont.systemFont(ofSize: 12)
cell2.backgroundColor = UIColor.red
return cell2
where I want to detect if array in cell have value (0 or 1) then label of cell take value from cellString1 or cellString2 and show text of this label. When I delete cells textLabel configuration, colors of cells background are correct (black, red, red, black, red) however in full code I have error (Index out of range) in line cell.textLabel?.text = cellString1[indexPath.row].
Is possible to fix that?
This should be :
destination.cellString1 = data1
destination.cellString2 = data2
destination.array = array
let destination = segue.destination as! DestinationController
you should perform segue after destination.cellString1 = data1, destination.cellString2 = data2 and destination.array = array. Else these properties won't be assigned.
This is expected because the 3 arrays have different count , and sure indexPath will exceed for cellString1 as it contains 2 items , and second "0" of array is in index 3 which exceeds count of cellString1
You got 2 titles, 3 descriptions and 5 color flags. If you are using multiple arrays as data source you have to make sure that the number of items are always the same.
For example if you return array.count in numberOfRows then cellForRow is called 5 times. But there is no item at indexPath.row > 1 in cellString1 and indexPath.row > 2 in cellString2. This causes the out-of-range exception.
Basically you are strongly discouraged from using multiple arrays as data source. Don't do that.
Use a custom struct instead and rather than "0" and "1" strings use a Bool
struct Item {
var title : String
var description : String
var colorFlag : Bool
}
Then create Item instances with the appropriate data and pass one array.
I've two arrays:
var filteredTitles = [String]()
var filteredTypes = [String]()
I filter the first array as a part of using searchbar. The order of the elements might change completely. However, I can't filter the second array the same way I did the first one, because I don't want to take it in to count when searching. But I would like for the second array to be in the same order as the first one. So, to recap. How can I filter an array to match another one by indexes perfectly?
An example:
var filteredArray = ["One", "Two", "Three"]
//Sort the below array to ["1", "2", "3"], the order of the upper array
var toBeFilteredArray = ["2", "1", "3"]
WITHOUT using alphabetical or numerical order, as that won't do in this case.
EDIT:
TO Russell:
How do I sort the titles like this:
// When there is no text, filteredData is the same as the original data
// When user has entered text into the search box
// Use the filter method to iterate over all items in the data array
// For each item, return true if the item should be included and false if the
// item should NOT be included
searchActive = true
filteredData = searchText.isEmpty ? original : original.filter({(dataString: String) -> Bool in
// If dataItem matches the searchText, return true to include it
return dataString.range(of: searchText, options: .caseInsensitive) != nil
})
don't have two arrays - have a single array of a custom type, containing both variables that you need
Define your struct
struct MyCustomData
{
var dataTitle : String = ""
var dataType : String = ""
}
and then declare it
var dataArray : [MyCustomData] = []
populate it and sort it where required - I have populated in reverse order just so that we can see it being sorted
dataArray.append(MyCustomData(dataTitle: "Third", dataType: "3"))
dataArray.append(MyCustomData(dataTitle: "Second", dataType: "2"))
dataArray.append(MyCustomData(dataTitle: "First", dataType: "1"))
let filteredArray = dataArray.sorted {$0.dataTitle < $1.dataTitle}
for filteredElement in filteredArray
{
print("\(filteredElement.dataTitle), \(filteredElement.dataType)")
}
// or, to print a specific entry
print("\(filteredArray[0].dataTitle), \(filteredArray[0].dataType)")
An example of keeping two separate arrays in sync using zip:
let titles = ["title1", "title3", "title4", "title2"]
let types = ["typeA", "typeB", "typeC", "typeD"]
let zipped = zip(titles, types)
// prints [("title4", "typeC"), ("title2", "typeD")]
print(zipped.filter { Int(String($0.0.characters.last!))! % 2 == 0 })
You can use map on the filtered result to get back two separate filtered arrays for the titles and types.
newbie to swift, a contrived example.
I have an array of menu categories, which in turn have menu items
I want to loop through the categories and then read the elements of the sub-array of items. Don't know the syntax to reference the element as an array
ERROR at line 10, col 18: type 'String' does not conform to protocol 'Sequence'
for (item) in offering {
var menuOffering = ["drinks" , "breakfastEntree"]
var drinks: Set = ["water","milk","coffee","tea","diet coke"]
var breakfastEntree: Set = ["eggs", "bacon", "sausage","pancakes"]
for ( offering) in menuOffering {
print ("\(offering)")
for (item) in offering { ERROR
print ("\(item)")
}
}
menuOffering is a String array because you have defined it in quotes. In this case drinks and breakfastEntree. So you are trying to iterate over a String and getting error. Instead, define your array menuOffering as follow:
var menuOffering = [drinks , breakfastEntree] // without quotes
Now it will be array of sets.
You modified code should be :
var drinks: Set = ["water","milk","coffee","tea","diet coke"]
var breakfastEntree: Set = ["eggs", "bacon", "sausage","pancakes"]
var menuOffering = [drinks , breakfastEntree]
for ( offering) in menuOffering {
for (item) in offering {
print ("\(item)")
}
}
menuOffering is an Array of Sets. Without the quotes, the variable names now access the sets' contained values and they can be iterated over in the nested form you'll see below.
let drinks: Set = ["water", "milk", "coffee", "tea", "diet coke"]
let breakfastEntree: Set = ["eggs", "bacon", "sausage", "pancakes"]
let menuOffering = [drinks, breakfastEntree]
for offering in menuOffering {
for item in offering {
print(item)
}
}
You can also print variables out I did above if you are not trying to include a variable name in a String as below:
print("string: \(variableName)")
Make sure not to include a space between "print" and the parentheses.
I have dictionary like this
var dict : [String : Array<String>] = ["Fruits" : ["Mango", "Apple", "Banana"],"Flowers" : ["Rose", "Lotus","Jasmine"],"Vegetables" : ["Tomato", "Potato","Chilli"]]
I want to get values in array for each key How to get it in swift?
2½ years and no-one mentioned map?
ok, set aside that Dictionary has a property values(as ameenihad shows) which will do what you asking for, you could do:
let values = dict.map { $0.value }
try this:
for (key, value) in dict {
println("key=\(key), value=\(value)")
}
Try to get values as like following code
let fruits = dict["Fruits"]
let flowers = dict["Flowers"]
let vegetables = dict["Vegetables"]
Try:
var a:Array = dict["Fruits"]! ;
println(a[0])//mango
println(a[1])//apple
for val in dict.values {
print("Value -> \(val)")
}
EDIT:
Try Something like this,
var dict : [String : Array<String>] = [
"Fruits" : ["Mango", "Apple", "Banana"],
"Flowers" : ["Rose", "Lotus","Jasmine"],
"Vegetables" : ["Tomato", "Potato","Chilli"]
]
var myArray : Array<String> = []
// You can access the dictionary(dict) by the keys(Flowers, Flowers, Vegetables)
// Here I'm appending the array(myArray), by the accessed values.
myArray += dict["Fruits"]!
myArray += dict["Vegetables"]!
print("myArray \(myArray)")
Above is how to get values of dictionay in swift,
If you want to get contatenated array of all the values of
dictionary(*only values),
Try something like below.
print("values array : \(dict.map{$0.value}.flatMap{$0})")
values array : ["Rose", "Lotus", "Jasmine", "Tomato", "Potato",
"Chilli", "Mango", "Apple", "Banana"]