Find Scalable solution to print data from Array in Swift - ios

I have an array starting from 1 to 100 and I have to print element if the number is divisible by 4 it should print the letter "A" and if the number is divisible by 5 it should print the letter "B" and if it is divisible by both then "AB" I want to make a scalable solution if in future I want to add number divisible by 8 should print "C" and divisible by 4 & 8 should print "AC", by 5&8 should print "BC" and if all three then "ABC"
desired output:
1
2
3
A
B
6
7
C
9
B
11
AB
13
14
...
I wrote this
for number in 1...100 {
if number.isMultiple(of: 4) && !number.isMultiple(of: 5){
print("A"
} else if !number.isMultiple(of: 4) && number.isMultiple(of: 5){
print("B")
} else if number.isMultiple(of: 4) && number.isMultiple(of: 5){
print("AB")
} else {
print(number)
}
}
Please provide a scalable solution to keep adding If-else is not a good option.

You were pretty close but you don't need the else conditions. Just add the character to the string if it matches another condition:
for number in 1...100 {
var string = ""
if number.isMultiple(of: 4) { string.append("A") }
if number.isMultiple(of: 5) { string.append("B") }
if number.isMultiple(of: 8) { string.append("C") }
print(string.isEmpty ? number : string)
}
Using a dictionary to store the characters:
let dict = [
4: "A",
5: "B",
8: "C"
]
for number in 1...100 {
var string = ""
for (key, character) in dict where number.isMultiple(of: key) {
string.append(character)
}
print(string.isEmpty ? number : string)
}
Note that dictionary is an unordered collection. If you need the characters to be sorted you would need to sort the dictionary by its values before iterating its key value pairs:
let sortedDict = dict.sorted(by: { $0.value < $1.value })
for number in 1...100 {
var string = ""
for (key, character) in sortedDict where number.isMultiple(of: key) {
string.append(character)
}
print(string.isEmpty ? number : string)
}

Here it is, instead of using if-else, you can just add up whenever you need
var stringArray = [String]()
for number in 0...100 {
stringArray.append(String(number))
}
// stringArray = ["0","1", "2", "3",....,"99", "100"]
// Adding a zero before to compare with the index
stringArray = stringArray.enumerated().map({ index, item in
var value = item
if index % 4 == 0 {
value = Int(item) == nil ? item + "A": "A"
}
return value
})
stringArray = stringArray.enumerated().map({ index, item in
var value = item
if index % 5 == 0 {
value = Int(item) == nil ? item + "B": "B"
}
return value
})
stringArray = stringArray.enumerated().map({ index, item in
var value = item
if index % 8 == 0 {
value = Int(item) == nil ? item + "C": "C"
}
return value
})
stringArray.removeFirst()
print(stringArray)
Result::
"1", "2", "3", "A", "B", "6", "7", "AC", "9", "B", "11", "A", "13", "14", "B", "AC", "17", "18", "19", "AB", "21", "22", "23", "AC", "B", "26", "27", "A", "29", "B", "31", "AC", "33", "34", "B", "A", "37", "38", "39", "ABC", "41", "42", "43", "A", "B", "46", "47", "AC", "49", "B", "51", "A", "53", "54", "B", "AC", "57", "58", "59", "AB", "61", "62", "63", "AC", "B", "66", "67", "A", "69", "B", "71", "AC", "73", "74", "B", "A", "77", "78", "79", "ABC", "81", "82", "83", "A", "B", "86", "87", "AC", "89", "B", "91", "A", "93", "94", "B", "AC", "97", "98", "99", "AB"
if you just want [Any] type then just
var resultArray = [Any]()
resultArray = stringArray.map({ number in
if let num = Int(number) { return num }
else { return number }
})
print(resultArray)

Related

How to group array of objects with same key value pair

I have an array of dictionaries with same key value pairs.
[
{ "amount": "10" },
{ "amount": "20" },
{ "amount": "30" },
{ "amount": "20" },
{ "amount": "10" },
{ "amount": "10" }
]
I need to group this based on same key values.
Expected sample result:
There are 3x 10's, 2x 20's and 1x 30's
How do I achieve this?
let array = [ ["amount": "10"], ["amount": "20"], ["amount": "30"], ["amount": "20"], ["amount": "10"], ["amount": "10"] ]
var result: [String: Int] = [:]
let key = "amount"
array.forEach {
guard let value = $0[key] else { return }
result[value, default: 0] += 1
}
print("\(result["10"])") // 3

How to add object in array after every 3 objects in array?

I have an array from 0 to 100.
let array = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"...."100"]
now, I want to add "-" after every 3 objects in an array.
So the output would be like this
array = ["0", "1", "2","-","3", "4", "5","-", "6", "7", "8", "-","9"...."100"]
So, How can I achieve this?
and what if i have model array instead of String array?
struct SubCategory {
var title: String = ""
var subTitle: String = ""
}
let array = [SubCategory]()
let array = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
extension Array {
func chunks(of size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
let n = Swift.min(size, count - $0)
return Array(self[$0 ..< $0 + n])
}
}
}
let joined = Array(array.chunks(of: 3).joined(separator: ["-"]))
Here is a way to directly create the result with a single map and a bit of math:
extension Array {
func adding(_ element: Element, afterEvery n: Int) -> [Element] {
guard n > 0 else { fatalError("afterEvery value must be greater than 0") }
let newcount = self.count + self.count / n
return (0 ..< newcount).map { (i: Int) -> Element in
(i + 1) % (n + 1) == 0 ? element : self[i - i / (n + 1)]
}
}
}
Example:
let result = ["0", "1", "2", "3", "4", "5", "6"].adding("-", afterEvery: 3)
print(result)
Output:
["0", "1", "2", "-", "3", "4", "5", "-", "6"]
Example 2:
This time with [Int]:
let result2 = [1, 2, 3, 4, 5, 6].adding(0, afterEvery: 2)
print(result2)
Output:
[1, 2, 0, 3, 4, 0, 5, 6, 0]
Example 3:
With a custom struct:
struct SubCategory: CustomStringConvertible {
var title = ""
var subTitle = ""
var description: String { return "SubCategory(title: \(title), subTitle: \(subTitle)" }
}
let array: [SubCategory] = [
SubCategory(title: "2001", subTitle: "A Space Odyssey"),
SubCategory(title: "Star Wars Episode 1", subTitle: "The Phantom Menace"),
SubCategory(title: "Star Wars Episode 2", subTitle: "Attack of the Clones"),
SubCategory(title: "Star Wars Episode 3", subTitle: "Revenge of the Sith"),
SubCategory(title: "Star Wars Episode 4", subTitle: "A New Hope"),
SubCategory(title: "Star Wars Episode 5", subTitle: "The Empire Strikes Back"),
SubCategory(title: "Star Wars Episode 6", subTitle: "Return of the Jedi")
]
let result3 = array.adding(SubCategory(title: "none", subTitle: "none"), afterEvery: 3)
print(result3)
Output:
[SubCategory(title: 2001, subTitle: A Space Odyssey, SubCategory(title: Star Wars Episode 1, subTitle: The Phantom Menace, SubCategory(title: Star Wars Episode 2, subTitle: Attack of the Clones, SubCategory(title: none, subTitle: none, SubCategory(title: Star Wars Episode 3, subTitle: Revenge of the Sith, SubCategory(title: Star Wars Episode 4, subTitle: A New Hope, SubCategory(title: Star Wars Episode 5, subTitle: The Empire Strikes Back, SubCategory(title: none, subTitle: none, SubCategory(title: Star Wars Episode 6, subTitle: Return of the Jedi]
Mutating version
Here is a version that mutates the original array instead of creating a new one:
extension Array {
mutating func add(_ element: Element, afterEvery n: Int) {
guard n > 0 else { fatalError("afterEvery value must be greater than 0") }
var index = (self.count / n) * n
while index > 0 {
self.insert(element, at: index)
index -= n
}
}
}
Example:
var array = ["0", "1", "2", "3", "4", "5", "6"]
array.add("-", afterEvery: 3)
print(array)
Output:
["0", "1", "2", "-", "3", "4", "5", "-", "6"]

Array of dictionary comparision - swift3

I have 2 array of dictionaries. I want to write a function which compare these 2 arrays.
Function should return true only if main array contains sub array element.
Else it should return false.
Here is my logic-
let mainArry = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 3, "name": "B", "price": "$1"]], ["id":"2","products":["pid": 14, "name": "C", "price": "$15"]]]
let array1 = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 3, "name": "B", "price": "$1"]]]
let array2 = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 4, "name": "B", "price": "$1"]]]
func compareDictionary(mainArry:[[String: Any]], arr2: [[String: Any]])-> Bool{
let itemsId = arr2.map { $0["id"]! } // 1, 3, 14
let filterPredicate = NSPredicate(format: "id IN %#", itemsId)
let filteredArray = mainArry.filter{filterPredicate.evaluate(with:$0) }
if filteredArray.count != arr2.count {
return false
}
for obj in filteredArray {
let prd = obj as Dictionary<String, Any>
let str = prd["id"] as! String
let searchPredicate = NSPredicate(format: "id == %#", str )
let filteredArr = arr2.filter{searchPredicate.evaluate(with:$0) }
if filteredArr.isEmpty {
return false
}
if !NSDictionary(dictionary: obj["products"] as! Dictionary<String, Any>).isEqual(to: filteredArr.last!["products"] as! [String : Any]) {
return false
}
}
return true
}
let result1 = compareDictionary(mainArry: mainArry, arr2: array1)
let result2 = compareDictionary(mainArry: mainArry, arr2: array2)
print("Result1 = \(result1)") // true
print("Result2 = \(result2)") //false
It is working. But I want to know the best way to achieve this.
Instead of using for-loop for comparision.
I want to use filter like this
let arrayC = filteredArray.filter{
let dict = $0
return !arr2.contains{ dict == $0 }
}
if arrayC is empty that means both arrays are equal.
I got it Finally!
We don't need to write big function.
let mainArry = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 3, "name": "B", "price": "$1"]], ["id":"2","products":["pid": 14, "name": "C", "price": "$15"]]]
let array1 = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 3, "name": "B", "price": "$1"]]]
let array2 = [ ["id":"1","products":["pid": 1, "name": "A", "price": "$5"]], ["id":"3","products":["pid": 4, "name": "B", "price": "$1"]]]
let result = array2.filter{
let dict = $0
return !mainArry.contains{
return NSDictionary(dictionary: dict).isEqual(to: $0)
}
}
if result.isEmpty {
print("Same key values")
} else {
print("Diff key values")
}

swift 4 split array and filter

i will build a UICollectionView with sections.
The sections are based on the return value from json.category.
the json format is like:
[{"id":"1",
"name":"Apple",
"category":"Fruits"},
{"id":"2",
"name":"Pie",
"category":"Fruits"},
{"id":"3",
"name":"Tomato",
"category":"Vegetable"}]
I need a array filter hat the array is something like: (for sectionsItems and sectionNames)
CategorieNames[STRING] = ["Fruits","Vegetable"] // the section names from json.category
Fruits = [STRING] = ["Apple","Pie"]
Vegetables = [STRING] = ["Tomato"]
Categories.append[Fruits]
Categories.append[Vegetables]
Categories[[STRING]] = [[Fruits],[Vegetable]]
Try bellow code.
let arrData = [["id": "1",
"name": "Apple",
"category": "Fruit"],
["id": "2",
"name": "Pie",
"category": "Fruit"],
["id": "3",
"name": "Tomato",
"category": "Vegetable"]]
let categorieNames = Array(Set(arrData.map({$0["category"]!})))
var arrResult:[[String]] = []
for i in 0..<categorieNames.count {
let categories = arrData.filter({$0["category"] == categorieNames[i]}).map({$0["name"]!})
arrResult.append(categories)
}
print("result : \(arrResult)")
result : [["Apple", "Pie"], ["Tomato"]]
you can do it as follows:
let arrData = [["id": "1",
"name": "Apple",
"category": "Fruit"],
["id": "2",
"name": "Pie",
"category": "Fruit"],
["id": "3",
"name": "Tomato",
"category": "Vegetable"]]
var categorys = [[String]]()
var fruits = [String]()
var vegetable = [String]()
for data in arrData {
if let category = data["category"] {
if category == "Fruit"{
if let aFruit = data["name"] {
fruits.append(aFruit)
}
}
else if category == "Vegetable" {
if let aVeggeie = data["name"] {
vegetable.append(aVeggeie)
}
}
}
}
categorys.append(fruits)
categorys.append(vegetable)

How to use a struct with a library in a tableview

I have created a struct with a library and have initialised that struct in another struct. Now I want to use the resulting struct in a Table View. However, the struct currently doesn't work properly. I've tried to find out why, but seem to be stuck.
It looks like the issue is that the library doesn't get translated properly to the struct. For in instance, when I do a count on an instance of the struct, using the following code:
var personalDetailsStructExtra: [PersonalDetailsStruct] = []
personalDetailsStructExtra.count
It returns 0, while it should be 5 (See code below, there are 5 entries into the dictionary):
struct PersonalDetailsStructLibrary {
let library = [
[
"title": "Country",
"icon": "country.pdf",
"questions": ["Belgium", "France", "Germany", "Netherlands", "Sweden", "UK", "USA"]
],
[
"title": "Age",
"icon": "age.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
[
"title": "Gender",
"icon": "gender.pdf",
"questions": ["Male", "Female", "Other"]
],
[
"title": "Height",
"icon": "height.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
[
"title": "Weight",
"icon": "weight.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
] }
And
struct PersonalDetailsStruct {
var title: String?
var icon: UIImage?
var questions: [String] = []
init(index: Int) {
let personalDetailsStructLibrary = PersonalDetailsStructLibrary().library
let personalDetailsDictionary = personalDetailsStructLibrary[index]
title = personalDetailsDictionary["title"] as! String!
let iconNamePD = personalDetailsDictionary["icon"] as! String!
icon = UIImage(named: iconNamePD!)
questions += personalDetailsDictionary["artists"] as! [String]
} }
As you can see in the code I want use the struct to fill up a label (title), image (icon) and UITextView with UIPickerView (questions) in my table view.
Since it doesn't work, I'm looking for either:
A: Feedback on how to make this code work in a tableview
B: Whether I should use another method to populate the dynamic cells in my tableview
You have to initialize the personalDetailsStructExtra array, only then you would see the required count.
var personalDetailsStructExtra = [PersonalDetailsStruct]()
PersonalDetailsStructLibrary().library.count
let count = PersonalDetailsStructLibrary().library.count
for i in 0..<count {
personalDetailsStructExtra.append(PersonalDetailsStruct(index: i))
}
personalDetailsStructExtra.count // 5
A better option is to use the Library struct to construct and maintain all model objects.
struct PersonalDetailDataSource {
let library = [
[
"title": "Country",
"icon": "country.pdf",
"questions": ["Belgium", "France", "Germany", "Netherlands", "Sweden", "UK", "USA"]
],
[
"title": "Age",
"icon": "age.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
[
"title": "Gender",
"icon": "gender.pdf",
"questions": ["Male", "Female", "Other"]
],
[
"title": "Height",
"icon": "height.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
[
"title": "Weight",
"icon": "weight.pdf",
"questions": ["1", "2", "3", "4", "5", "6", "7"]
],
]
var personalDetails = [PersonalDetail]()
init() {
loadData()
}
mutating private func loadData() {
for i in 0..<library.count {
let personalDetailsDictionary = library[i]
let title = personalDetailsDictionary["title"] as! String!
let iconName = personalDetailsDictionary["icon"] as! String!
let questions = personalDetailsDictionary["questions"] as! [String]
personalDetails.append(PersonalDetail(title: title, iconName: iconName, questions: questions))
}
}
}
struct PersonalDetail {
var title: String?
var icon: UIImage?
var questions: [String] = []
init(title: String, iconName: String, questions: [String]) {
self.title = title
if let icon = UIImage(named: iconName) {
self.icon = icon
}
self.questions = questions
}
}
PersonalDetailDataSource().personalDetails.count // count: 5

Resources