How to concatenate a value from a dictionary with a string - swift

Given the following, what is the proper way to concatenate
var sets = [[ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ]]
var text = sets[0]["reps"] + " reps"
The only thing that worked was the code below, but I don't understand why. Ideally I can simply use string interpolation for this, but that seems to generate a syntax error.
var text = sets[0]["reps"]!.description + " reps"

Updated for Swift 2
sets is of type [[String : Int]]. So in order to get a String from your Int, you have to use string interpolation or use a String initializer.
According to your needs, you may choose one of the following Playground examples:
Optional binding + String initializer:
let sets = [[ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ]]
if let int = sets[0]["reps"] {
let text = String(int) + " reps"
print(text) // prints: "10 reps"
}
Optional binding + string interpolation:
let sets = [[ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ]]
if let int = sets[0]["reps"] {
let text = "\(int)" + " reps"
print(text) // prints: "10 reps"
}
Optional forced unwrapping:
let sets = [[ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ], [ "reps": 10, "weight": 100 ]]
let int = sets[0]["reps"]! // Use forced unwrapping with caution
let text = "\(int)" + " reps"
print(text) // prints: "10 reps"

sets[0]["reps"] is an int. You can use formatting to specify the types:
var weight = sets[0]["reps"]!
var text = String(format: "%d reps", weight)
or all in one:
var text = String(format: "%d reps", sets[0]["reps"]!)
println("text: \(text)") // text: 10 reps

Related

What is the best way to make this API request in Swift?

Sorry if this question is too repetitive here but I cant figured out how to made it :(
I need to send data to an API (https://www.opticutter.com/public/doc/api#introduction) my data comes from somes TextFields and this is what the API expect.
curl -H "Content-type: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-X POST -d '{
"stocks" : [{
"length" : "60",
"width" : "40",
"count": "10",
"grainDirection": null
},{
"length" : "40",
"width" : "35",
"grainDirection": null
}],
"requirements" : [{
"length" : "30",
"width" : "20",
"count": "8",
"grainDirection": null
},
{
"width" : "20",
"length" : "20",
"count": "3",
"grainDirection": null
}],
"settings" : {
"kerf": "0"
}
}'
So I already have the code to make the request but I cant realize how convert the data into that.
Hope do you understand what I need.
Thanks in advance!
The best approach in my opinion is to map your data into structs/classes and use the Decodable protocol.
struct Stock: Encodable {
let length: Int
let width: Int
let count: Int
let grainDirection: Int?
}
struct Requirement: Encodable {
let length: Int
let width: Int
let count: Int
let grainDirection: Int?
}
struct Setting: Encodable {
let kerf: Int
}
struct MyObject: Encodable {
let stocks: [Stock]
let requirements: [Requirement]
let settings: [Setting]
}
Then you build the MyObject with the data from the textfields:
let myObjectData = MyObject(stocks: [
Stock(length: 60, width: 40, count: 10, grainDirection: nil),
Stock(length: 40, width: 35, count: 0, grainDirection: nil)
],
requirements: [
Requirement(length: 30, width: 20, count: 8, grainDirection: nil),
Requirement(length: 20, width: 20, count: 3, grainDirection: nil),
],
settings: [Setting(kerf: 0)])
Finally on the request you would have to encode the data, converting it into a JSON String for example:
do {
let jsonData = try JSONEncoder().encode(myObjectData)
let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString)
} catch {
debugPrint(error)
}
This will produce a json string with the following result:
{
"stocks":[
{
"width":40,
"count":10,
"length":60
},
{
"width":35,
"count":0,
"length":40
}
],
"requirements":[
{
"width":20,
"count":8,
"length":30
},
{
"width":20,
"count":3,
"length":20
}
],
"settings":[
{
"kerf":0
}
]
}

Search in NSMutableArray

I am wanted to make a search on NSMUtableArray with key values to catch the hole object not just an array of values so for example my NSMUtableArray return me
{id : 1, name : x1}
{id : 2, name : x2}
{id : 3, name : x3}
{id : 4, name : y1}
{id : 5, name : y2}
if I am searching of x my code return me
{x1,x2,x3}
or I want it to return
{id : 1, name : x1}
{id : 2, name : x2}
{id : 3, name : x3}
my code is :
let arrayy = lstResults.value(forKey: "name")
let searchTest = NSPredicate(format: "SELF BEGINSWITH [c] %#", searchBar.text!)
let array = (arrayy as! NSArray).filtered(using: searchTest)
filteredTableDataName = array as NSArray
please help I tried a lot of stuff but nothing worked form me.
Instead of extracting and filtering the "name" values you can filter the array directly, using the corresponding key path instead of “SELF” in the predicate:
let array = NSArray(array: [
["id": 1, "name": "x1"], ["id": 2, "name": "x2"], ["id": 3, "name": "y3"]])
let predicate = NSPredicate(format: "name BEGINSWITH [c] %#", "x")
let filtered = array.filtered(using: predicate)
print(filtered)
Result:
[{
id = 1;
name = x1;
}, {
id = 2;
name = x2;
}]
Another option is to cast the NS(Mutable)Array to a Swift array of dictionaries, and use the filter() function:
if let a = array as? [[String: Any]] {
let filtered = a.filter {
($0["name"] as? String)?
.range(of: "x", options: [.caseInsensitive, .anchored]) != nil
}
print(filtered)
// [["id": 1, "name": x1], ["name": x2, "id": 2]]
}
NSMutableArray (or NSArray for that matter) are leftovers from the 'Objective-c' era.
For this purpose there is not real need using it or not using Swift's standard generic Array<Element> => https://developer.apple.com/documentation/swift/array
Might I consider creating a struct instead of using a dictionary:
import Foundation
struct Obj {
let id: Int
let name: String
}
let array = [
Obj(id: 1, name: "x1"),
Obj(id: 2, name: "x2"),
Obj(id: 3, name: "X3"),
Obj(id: 4, name: "y1"),
Obj(id: 5, name: "y2")
]
let filteredArray = array.filter { $0.name.localizedLowercase.hasPrefix("x") }
// filteredArray = [
// Obj(id: 1, name: "x1"),
// Obj(id: 2, name: "x2"),
// Obj(id: 3, name: "X3")
// ]
Else you would have something like this:
import Foundation
let array: [[String: Any]] = [
[ "id": 1, "name": "x1" ],
[ "id": 2, "name": "x2" ],
[ "id": 3, "name": "X3" ],
[ "id": 4, "name": "y1" ],
[ "id": 5, "name": "y2" ]
]
let filteredArray = array.filter { ($0["name"] as? String)?.localizedLowercase.hasPrefix("x") == true }

Counting letter occurrences in a String Swift

Found a cute way of counting the occurrences of character in a String:
let inputString = "test this string"
var frequencies : [Character: Int] = [:]
let baseCounts = zip(
inputString, repeatElement(1,count: Int.max))
frequencies = Dictionary(baseCounts, uniquingKeysWith: +)
with the result
["i": 2, "r": 1, "n": 1, "e": 1, "s": 3, " ": 2, "g": 1, "t": 4, "h": 1]
However I tried to use a range for the elements such that
let secondBaseCounts = zip(inputString, 0...)
frequencies = Dictionary(secondBaseCounts, uniquingKeysWith: +)
but get the incorrect result:
["i": 20, "r": 12, "n": 14, "e": 1, "s": 20, " ": 13, "g": 15, "t": 19, "h": 6]
Why?
Your second attempt doesn't implement what you meant to implement. zip(inputString, 0...) simply maps the Int index of each character to the character itself.
So the value of secondBaseCounts will be
["t", 0), ("e", 1), ("s", 2), ("t", 3), (" ", 4), ("t", 5), ("h", 6), ("i", 7), ("s", 8), (" ", 9), ("s", 10), ("t", 11), ("r", 12), ("i", 13), ("n", 14), ("g", 15)]
Calling Dictionary(secondBaseCounts, uniquingKeysWith: +) sums each value associated with repeating keys, meaning that the values in your final frequencies dictionary will be the sum of all indices where a certain character occurs in inputString rather than the count of occurrences of that character.
I am answering this question without using any Build-In methods. Most likely to be asked in Interviews.
var inputString = "test this string"
extension String {
func countCharacterOccurances() -> Dictionary<String, Any> {
var occuranceDict : [String : Int] = [:]
for i in self {
var count = 1
if occuranceDict[String(i)] == nil {
occuranceDict[String(i)] = count
}
else {
count = occuranceDict[String(i)] ?? 0
count += 1
occuranceDict[String(i)] = count
}
}
return occuranceDict as Dictionary<String, Any>
}
}
var characterOccuranceDict = inputString.countCharacterOccurances()
Output : ["h": 1, "t": 4, "i": 2, "g": 1, "s": 3, "r": 1, " ": 2, "n": 1, "e": 1]
The following code is useful if you want a dictionary that is sorted alphabetically by Keys. Otherwise, you can print characterOccuranceDict.
Problem statement:- "write a program to count consecutive characters in the string and combine them in a string in given order"
let sortedDictionary = characterOccuranceDict.sorted { $0.key < $1.key }
sortedDictionary.forEach { (item) in
finalStr = finalStr + item.key + String(describing: item.value)
}
print(finalStr)
inputString = "AAABBCCCCD"
Output : A3B2C4D1
swift ios

How to add multiple dictionary into array

I've got a dictionary added into array. I would like to add second dictionary into the array. How to do it?
var dict = [String: AnyObject]()
dict = ["description": self.odrRefTxt.text as AnyObject,
"weight": self.pWeight as AnyObject,
"quantity": self.qtyTxt.text as AnyObject,
"unitPrice": self.valueTxt.text as AnyObject,
"currency": self.pCurrency as AnyObject]
// saving to memory
UserDefaults.standard.set(dict, forKey: "addItem")
// getting from memory
let addItem = UserDefaults.standard.value(forKey: "addItem")
print(addItem as Any)
//add new item into list of items
self.itemArr.append(addItem as Any)
print(self.itemArr)
Below are the result from print:
//print addItem
Optional({
currency = "";
description = "Toyo Proxes";
quantity = 4;
unitPrice = 100;
weight = 0;
})
//print self.itemArr
[Optional({
currency = "";
description = "Toyo Proxes";
quantity = 4;
unitPrice = 100;
weight = 0;
})]
For example, I would like to add the 2nd dictionary into the array to print out the outcome like this:
//print self.itemArr
[Optional({
currency = "";
description = "Toyo Proxes";
quantity = 4;
unitPrice = 100;
weight = 0;
},
{
currency = "";
description = "Yokohama Advan";
quantity = 2;
unitPrice = 250;
weight = 0;
})]
You save something in UserDefaults as Any, so just cast it to the original type and here you go.
Modified with #rmaddy's suggestion.
var itemArr = [[String: Any]]()
var dict = [String: Any]()
dict = ["description": 1,
"weight": 2,
"quantity": 3,
"unitPrice": "abc",
"currency": "123"]
// saving to memory
UserDefaults.standard.set(dict, forKey: "addItem")
// getting from memory
if let addItem = UserDefaults.standard.dictionary(forKey: "addItem") {
itemArr.append(addItem)
}
let dict2:[String: Any] = ["description": 4,
"weight": 5,
"quantity": 6,
"unitPrice": "xyz",
"currency": "456"]
itemArr.append(dict2)
print(itemArr)
// prints out:
// [["description": 1, "quantity": 3, "weight": 2, "currency": 123, "unitPrice": abc], ["description": 4, "weight": 5, "quantity": 6, "currency": "456", "unitPrice": "xyz"]]

If a key is duplicated in an array,I want to add the values of that key

If a key is duplicated in an array, I want to combine the values of that key. For example, I have the following array.
var arrays = [
["Product":"Item0", "Price":"15"],
["Product":"Item1", "Price":"53"],
["Product":"Item2", "Price":"12"],
["Product":"Item1", "Price":"83"],
["Product":"Item0", "Price":"10"],
["Product":"Item3", "Price":"88"],
["Product":"Item0", "Price":"44"]
]
And I want to change this array like this.
[
["Product": "item0", "Price": "69"],
["Product": "item1", "Price": "136"],
["Product": "item2", "Price": "12"],
["Product": "item3", "Price": "88"]
]
What should I do?
This is the code I wrote. However, if more than two keys are duplicated, the exact value is not displayed. Could you fix a little here or give me a new way at all?
var arrays= [
["Product":"Item0", "Price":"15"],
["Product":"Item1", "Price":"53"],
["Product":"Item2", "Price":"12"],
["Product":"Item1", "Price":"83"],
["Product":"Item0", "Price":"10"],
["Product":"Item3", "Price":"88"],
["Product":"Item0", "Price":"44"]
]
var filteredArrays = [[String:String]]()
var sum : Int = 0
for i in 0..<arrayOfDicts.count {
let Product1 = arrayOfDicts[i]["Product"]
if(i == 0){
filteredArrays.append(arrayOfDicts[i])
} else {
var flag = false
for j in 0..<filteredArrays.count {
let Product2:String = filteredArrays[j]["Product"]!
if Product1 == Product2 {
sum += (Int(arrayOfDicts[i]["Price"]!)! + Int(arrayOfDicts[j]["Price"]!)!)
filteredArrays[j] = ["Product":"\(arrayOfDicts[i]["Product"]!)", "Price":"\(sum)"]
sum = 0
flag = true
}
}
if !flag {
filteredArrays.append(arrayOfDicts[i])
}
}
}
Thank you
Iterate through your products
Check if "Product" contains valid string
Extract price as Int (or float if needed). Default as zero to avoid wrong sum.
Create a dictionary with product name as key and sum the values with same key
Convert dictionary to array
var result = [String : Int]()
for product in arrays {
if let productKey = product["Product"] {
let value = Int(product["Price"] ?? "0")
if result[productKey] == nil, let value = value {
result[productKey] = value
} else if let value = value {
result[productKey]! += value
}
}
}
let newArray = result.map {["Product":$0, "Price": $1]}
Just for fun, not for the faint-hearted, using Swift 4 new method reduce(into:) and Dictionary Key-based subscript with default value:
let result = arrays.reduce(into: [String : Int]()) {
$0[$1["Product"] ?? "", default: 0] += Int($1["Price"] ?? "") ?? 0 }
.map { ["Product": $0, "Price": $1] }
print(result)
"[["Product": "Item0", "Price": 69], ["Product": "Item2", "Price":
12], ["Product": "Item1", "Price": 136], ["Product": "Item3", "Price":
88]]\n"