swift - if statement and array - ios

I want to match a string from the DicX to a an existing title (title of a table which changes according to the cell selection).
var DicX = ["xx",
"yy",
"zz",
"qq"]
let DicYY = [["11", "22", "33", "44"],
["1", "2", "3", "4"],
["m", "n", "k", "b"],
["bb", "kk", "mm", "nn"]]
the title I'm comparing with is like this:
title = detailX.insideTitle
so I want that when the title string equal to one of the DicX strings, to show the corresponding strings for it in DicYY each one of the 4 on a button.
but can't get the match correct, I tried to do like:
var currentX = detailX.insideTitle
if DicX == currentX["DicX"] {
}
I get this message :
Cannot subscript a value of type 'String' with an index of type 'String'
how can I do the if statement? and how to get the corresponding from DicYY?

This will do the job (if i got it right).
import Foundation
let DicX = ["xx",
"yy",
"zz",
"qq"]
let DicYY = [["11", "22", "33", "44"],
["1", "2", "3", "4"],
["m", "n", "k", "b"],
["bb", "kk", "mm", "nn"]]
let searchterm = "yy"
for (index, elem) in DicX.enumerated()
{
if (searchterm != elem) { continue }
print(DicYY[index]) // This will print ["1","2","3","4"]
}

Related

Swift: ArraySlice<Array<String>> to [[String]]

I have an array of type [[String]] and I am trying to move first 4 elements from the array to another array.
For example:
var arr1: [[String]] = [["1", "2", "3"], ["2", "3", "4"], ["3", "4", "5"], ["1", "2", "3"], ["2", "3", "4"], ["3", "4", "5"]]
var arr2: [[String]] = arr1[0...3]
But I am getting error saying that Cannot convert value of type 'Array<[String]>.SubSequence' (aka 'ArraySlice<Array<String>>') to specified type '[[String]]'
My required output is arr1 contains [["2", "3", "4"], ["3", "4", "5"]] and arr2 contains [["1", "2", "3"], ["2", "3", "4"], ["3", "4", "5"], ["1", "2", "3"]]
You have to (re)create an Array from the slice
let arr2 = Array(arr1[0...3])
Side note: It's not necessary to annotate types the compiler can infer.
In this case you could proceed without creating an array if the next step accepts a slice.
First initialize the array
var arr2: [[String]] = [[String]]()
Then you can add elements to your array using 'append'
arr2.append(contentsOf: arr1[0...3])

How to sort a CSV string based on the inner values?

I have this CSV String
"B,C,D,A,E\n18945,12091,14058,2907,15132\n25,122,134,428,211"
which I have separated by \n and , and got below array:
I have this array:
[["B", "C", "D", "A", "E"], ["18945", "12091", "14058", "2907", "15132"], ["25", "122", "134", "428", "211"]]
where first array inside the main array is indicating the column names, which I need to sort alphabetically based on that the remaining arrays should also sorted.
Consider a table like this:
B -> 18945 -> 25
After sort, I am expecting an output like this:
[["A", "B", "C", "D", "E"], ["2907", "18945", "12091", "14058", "15132"], ["428", "25", "122", "134", "211"]]
IMO you should try to structure your data but if you really want to go through this path you just need to sort the first collection indices and map the collections using the sorted indices. Of course this assumes all collections have the same number of elements and the collection is not empty:
let table = [["B", "C", "D", "A", "E"], ["18945", "12091", "14058", "2907", "15132"], ["25", "122", "134", "428", "211"]]
let indices = table[0].indices.sorted { table[0][$0] < table[0][$1] }
let sorted = table.map { collection in
indices.map { collection[$0] }
}
If you want to be extra paranoid and make sure your code will never crash you can get the first collection using if let and use compact map checking if the collection contains each index before accessing them using subscript:
let table = [["B", "C", "D", "A", "E"], ["18945", "12091", "14058", "2907", "15132"], ["25", "122", "134", "428", "211"]]
if let columns = table.first {
let indices = columns.indices.sorted { columns[$0] < columns[$1] }
let sorted = table.map { collection in
indices.compactMap { collection.indices ~= $0 ? collection[$0] : nil }
}
print(sorted)
}
edit/update:
For a case insensitive sort:
let indices = columns.indices.sorted { columns[$0].caseInsensitiveCompare(columns[$1]) == .orderedAscending }
For a case and diacritic insensitive sort:
let indices = columns.indices.sorted { columns[$0].localizedStandardCompare(columns[$1]) == .orderedAscending }
This will print
[["A", "B", "C", "D", "E"], ["2907", "18945", "12091", "14058", "15132"], ["428", "25", "122", "134", "211"]]

How to get value ForRowAt indexPath in tableview? [duplicate]

I want to match a string from the DicX to a an existing title (title of a table which changes according to the cell selection).
var DicX = ["xx",
"yy",
"zz",
"qq"]
let DicYY = [["11", "22", "33", "44"],
["1", "2", "3", "4"],
["m", "n", "k", "b"],
["bb", "kk", "mm", "nn"]]
the title I'm comparing with is like this:
title = detailX.insideTitle
so I want that when the title string equal to one of the DicX strings, to show the corresponding strings for it in DicYY each one of the 4 on a button.
but can't get the match correct, I tried to do like:
var currentX = detailX.insideTitle
if DicX == currentX["DicX"] {
}
I get this message :
Cannot subscript a value of type 'String' with an index of type 'String'
how can I do the if statement? and how to get the corresponding from DicYY?
This will do the job (if i got it right).
import Foundation
let DicX = ["xx",
"yy",
"zz",
"qq"]
let DicYY = [["11", "22", "33", "44"],
["1", "2", "3", "4"],
["m", "n", "k", "b"],
["bb", "kk", "mm", "nn"]]
let searchterm = "yy"
for (index, elem) in DicX.enumerated()
{
if (searchterm != elem) { continue }
print(DicYY[index]) // This will print ["1","2","3","4"]
}

How to get proper string array in swift?

["[\"1\", \"7\", \"13\", \"19\", \"25\"]", "[\"6\", \"12\", \"13\"]"]
I am getting this as output how to get string array like this in Swift
["1", "7", "13", "19", "25", "6", "12", "13"]
I tried all to convert this array in proper array but no luck. Is there a solution for this ?
Thank You!!
Simple solution (without significant error handling), the strings can be treated as JSON
let array = ["[\"1\", \"7\", \"13\", \"19\", \"25\"]", "[\"6\", \"12\", \"13\"]"]
var result = [String]()
for item in array {
let jsonArray = try! JSONSerialization.jsonObject(with: item.data(using: .utf8)!) as! [String]
result.append(contentsOf: jsonArray)
}
print(result)
First, assuming you had a simple array of arrays, you can flatten it with flatMap:
let input = [["1", "7", "13", "19", "25"], ["6", "12", "13"]]
let output = input.flatMap { $0 }
That outputs
["1", "7", "13", "19", "25", "6", "12", "13"]
Or, even easier, just append the second array to the first one, bypassing the array of arrays altogether:
let array1 = ["1", "7", "13", "19", "25"]
let array2 = ["6", "12", "13"]
let output = array1 + array2
But your example looks like it's not an array of arrays, but rather array of descriptions of arrays, e.g. something like:
let array1 = ["1", "7", "13", "19", "25"]
let array2 = ["6", "12", "13"]
let input = ["\(array1)", "\(array2)"]
let output = ... // this is so complicated, I wouldn't bother trying it
Rather than figuring out how to reverse this array of interpolated strings, I'd suggest you revisit how you built that, bypassing interpolated strings (or description of the arrays).

Merge few lists into dictionary

I have 3 lists:
a = ["John", "Archie", "Levi"]
b = ["13", "20"]
c = ["m", "m", "m", "m"]
I want to merge this into one list with dictionaries:
result = [
{"name": "John", "age": "13", "gender": "m"},
{"name": "Archie", "age": "20", "gender": "m"},
{"name": "Levi", "age": "", "gender": "m"},
{"name": "", "age": "", "gender": "m"},
]
Ok, this is pretty normal computer science problem. Here is an outline of how to go about solving it:
First, identify the inputs and the desired outputs. You've done that.
Note any edge cases you need to handle
Next, map out the logic flow using pseudo-code.
Convert from pseudo-code to real code.
Test and debug.
For step 2, your data suggests that you want to handle cases where you have different numbers of elements in each source array. it looks like you want to create a dictionary for all the 0 elements in each array, then a dictionary for the 1 elements, etc. When you run out of elements for a given array, it looks like you want to skip that key in your resulting dictionary entry.
Now to pseudo-code:
Find the array with the maximum number of elements. Make this your output_count (the number of items in your output array.)
Create an output array large enough for output_count entries.
Loop from 0 to output_count - 1.
create a dictionary variable
for each input array, if there are enough elements, add a key/value pair
for that array's key and the value at the current index. Otherwise skip
that key.
add the new dictionary to the end of your output array.
That should be enough to get you started. Now see if you can convert that pseudo-code to actual code, test it, and debug it. Report back here with your actual code, and feel free to ask for help if you get stuck getting your code working.
Try like this:
let a = ["John", "Archie", "Levi"]
let b = ["13", "20"]
let c = ["m", "m", "m", "m"]
var dicArray:[[String:String]] = []
for index in 0..<max(a.count,b.count,c.count) {
dicArray.append([:])
dicArray[index]["name"] = index < a.count ? a[index] : ""
dicArray[index]["age"] = index < b.count ? b[index] : ""
dicArray[index]["gender"] = index < c.count ? c[index] : ""
}
dicArray // [["gender": "m", "age": "13", "name": "John"], ["gender": "m", "age": "20", "name": "Archie"], ["gender": "m", "age": "", "name": "Levi"], ["gender": "m", "age": "", "name": ""]]
Here is my take. I first create the array, and then use enumerate() and forEach to process each array and add them to the array of dictionaries:
let a = ["John", "Archie", "Levi"]
let b = ["13", "20"]
let c = ["m", "m", "m", "m"]
let count = max(a.count, b.count, c.count)
var result = Array(count: count, repeatedValue: ["name":"", "age":"", "gender":""])
a.enumerate().forEach { idx, val in result[idx]["name"] = val }
b.enumerate().forEach { idx, val in result[idx]["age"] = val }
c.enumerate().forEach { idx, val in result[idx]["gender"] = val }
print(result)
[["gender": "m", "age": "13", "name": "John"], ["gender": "m", "age":
"20", "name": "Archie"], ["gender": "m", "age": "", "name": "Levi"],
["gender": "m", "age": "", "name": ""]]
This should do the job
let maxLength = max(a.count, b.count, c.count)
let paddedA = a + [String](count: maxLength-a.count, repeatedValue: "")
let paddedB = b + [String](count: maxLength-b.count, repeatedValue: "")
let paddedC = c + [String](count: maxLength-c.count, repeatedValue: "")
let res = zip(paddedA, zip(paddedB, paddedC)).map {
["name": $0.0, "age": $0.1.0, "gender": $0.1.1]
}
Output
[["gender": "m", "age": "13", "name": "John"], ["gender": "m", "age": "20", "name": "Archie"], ["gender": "m", "age": "", "name": "Levi"], ["gender": "m", "age": "", "name": ""]]

Resources