I am trying to convert a String into a Double value in Swift. After doing a lot of research, I believe that this would be the best method to turn my string to an Double. But now I am getting an error that I have no idea of how to fix.
var purchaseAmount: Double = 200
var cashTendered: Double = 425.45
var changeRequired: Double = 0
var currencyValues = ["100", "50", "20", "10", "5", "2", "1", "0.50", "0.20", "0.10", "0.05"]
import Cocoa
if cashTendered < purchaseAmount {
println("Not enough cash tendered")
} else {
changeRequired = cashTendered - purchaseAmount
for currency in currencyValues {
var doubleCurrency = (currency as NSString).doubleValue
var amountOfCurrency = changeRequired / doubleCurrency
amountOfCurrency = floor(amountOfCurrency)
changeRequired = changeRequired - (amountOfCurrency * currency)
changeRequired = round(changeRequired * 100)/100
println("$\(currency) X \(Int(amountOfCurrency))")
}
}
Here is the error:
What do I have to do to solve this problem?
First of all initialise String array like below:
let currencyValues : [String] = ["100", "50", "20", "10", "5", "2", "1", "0.50", "0.20", "0.10", "0.05"]
However it is not required type declaration because of Swift has vital feature Type Interface. But most of the practice it is good to define type while working with array.
And about converting string to double you can use below code:
for currency : String in currencyValues {
let doubleCurrency = NSNumberFormatter().numberFromString(currency)!.doubleValue
print(doubleCurrency)
}
Posting code would be easier to look at than an image, but if all else fails there is NSNumberFormatter. Other advantage of NSNumberFormatter would allow you to convert both directions and get nice output for things like currency.
Related
This is code has been driving me crazy, it's so simple but cannot get it to work. I have followed several examples and help from the forum, but the XOR is not working. The problem is when I extract the char from the string array and convert it to an ASCII value it's a Uint8 rather than an Int. So the XOR does not work, how can I convert an Uint8 to an int?
// Convert the data into the string
for n in 0...7
{
print("Inside the password generator for loop /(n)")
let a:Character = SerialNumber_hex_array[n]
var a_int = a.asciiValue
let b:Character = salt_arrary[n]
let b_int = b.asciiValue
// This does not work as the a_int & b_int are not int !!!
// How to convert the Uint8 to int?
let xor = (a_int ^ b_int)
// This code works
var a1 = 12
var b1 = 25
var result = a1 ^ b1
print(result) // 21
}
To convert your UInt8? to Int, use an available Int initializer:
let a_int = Int(a.asciiValue!)
let b_int = Int(b.asciiValue!)
let xor = (a_int ^ b_int) // compiles
This direct approach requires force unwrapping but I assume the hex array looks like below and your characters are hard coded for safety. If not, unwrap these unsigned integers safely with if-else or guard.
let SerialNumber_hex_array: [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]
I working on an app to show some information about cities
In an array I have two parameters
1- languages (I don't know how many there are)
2- the number of people that speak on that language
I get this data from an server
here is this two paramter in JSon
"language": "French",
"number": "12321",
these data among other data is saved in an array
I Just want to get the most used language with the pecentage
for example French with 35%
how can I do it in swift?
Your help will be appreciated.
import Foundation
let serverOutput = Data("""
[
{
"language": "French",
"number": "12"
},
{
"language": "English",
"number": "10"
}
]
""".utf8)
struct LangueUsers: Codable {
let language: String
let number: Int
enum CodingKeys: CodingKey {
case language
case number
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
language = try container.decode(String.self, forKey: .language)
let rawNumber = try container.decode(String.self, forKey: .number)
guard let number = Int(rawNumber) else {
throw DecodingError.typeMismatch(Int.self, DecodingError.Context(codingPath: [CodingKeys.number], debugDescription: "\(rawNumber) can't be convert to Int"))
}
self.number = number
}
}
struct LangueUsersPercent: CustomStringConvertible {
let language: String
let share: Double
init(language: String, number: Int, all: Int) {
self.language = language
self.share = Double(number) / Double(all)
}
var description: String {
return String(format: "%# - %0.1f%%", language, share * 100)
}
}
let decoder = JSONDecoder()
//1
var output = try decoder.decode([LangueUsers].self, from: serverOutput)
//2
let allUser = output.reduce(0) { (reult, languageUsers) -> Int in
reult + Int(languageUsers.number)
}
//3
output.sort { (lhs, rhs) -> Bool in
lhs.number > rhs.number
}
//4
let response = output.map {
LangueUsersPercent(language: $0.language, number: $0.number, all: allUser)
}
print(response[0])
The code assumes that the output from a server is in serverOutput variable. So steps need to achieve your task:
decode your JSON to swift structure (called LangueUsers) using swift codable. Keep in mind that by default it won't convert string values to int, so I have to create a custom init(from decoder: Decoder) initializer
count the sum of all users (you can do it using for loop or reduce like in my example)
sort your list, so the language with the most users will be first
this step is optional, but I've added a separate structure that will help us generate output and in this step, we are rewriting our input structures to output ones
Hope this is clear for you. Let me know if you have any questions.
The simplest way is:
// Example JSON
const exampleJSON = {
"people": [
{
"language": "French",
"number": 12321,
},
{
"language": "English",
"number": 7000,
}
]
};
// Parse it
const parsed = JSON.parse(JSON.stringify(exampleJSON));
const speakers = [...parsed.people];
// Count number of all speakers and let it be as 100%
let sumAllSpeakers = 0;
parsed.people.reduce((previous, current) => {
sumAllSpeakers = previous.number + current.number;
return previous;
});
// Compare fucntion
const compareSpeakers = (speaker1, speaker2) => {
if (speaker1.number > speaker2.number) {
return -1;
}
if (speaker1.number < speaker2.number) {
return 1;
}
return 0;
}
// Create new array with statistic sorted from max number
const statisticsOfSpeakersInPersent = speakers
.sort((speaker1, speaker2) => compareSpeakers(speaker1, speaker2))
.map(speaker => {
return {...speaker, ...{inPersent: speaker.number * 100 / sumAllSpeakers + '%'}}
});
I hope this example helps you.
Out:
[ { language: 'French',
number: 12321,
inPersent: '63.76999120128358%' }, { language: 'English',
number: 7000,
inPersent: '36.23000879871642%' } ]
I 'm having an array of dictionary like so...
[
{
"id" : "3",
"sellingPrice" : "520",
"quantity" : "15"
},
{
"id" : "5",
"sellingPrice" : "499",
"quantity" : "-1"
},
{
"id" : "8",
"sellingPrice" : "500",
"quantity" : "79"
}
]
Now I want to add to the dictionary another key called remaining_balance with a value of 420,499 & 500 respectively. How can I achieve this..? Hope somebody can help...
It seems like you want to add a value to your dictionary that is an array:
var arrDict = Array<Dictionary<String,Any>>() //Your array
arrDict.append(["id":"3","sellingPrice":"520","quantity":"13"])
arrDict.append(["id":"5","sellingPrice":"43","quantity":"32"])
arrDict.append(["id":"8","sellingPrice":"43","quantity":"33"])
let arrValue = ["420","499","500"] //Your remaining value in array
print("Before ",arrDict)
for (index,dict) in arrDict.enumerated() {
var dictCopy = dict //assign to var variable
dictCopy["remaining_balance"] = arrValue[index]
arrDict[index] = dictCopy //Replace at index with new dictionary
}
print("After ",arrDict)
EDIT
If you are able keep an index of an array it would be possible,
Assuming that you have the index of an array
var dictCopy = arrDict[index]
dictCopy["remaining_balance"] = "666" //Your calculated value
arrDict[index] = dictCopy //Replace at index with new dictionary
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
let array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
let newArray = array.enumerated().map { (index : Int, value: [String: String]) -> [String: String] in
var dic = value
dic.merge(newKV[index]) { (_, new) -> String in
new
}
return dic
}
You could achieve it by mapping your array:
var myArray = [["id": "3", "sellingPrice": "520", "quantity" : "15"], ["id": "5", "sellingPrice": "499", "quantity" : "-1"], ["id": "8", "sellingPrice": "500", "quantity" : "79"]]
print(myArray)
/*
[["id": "3", "sellingPrice": "520", "quantity": "15"],
["id": "5", "sellingPrice": "499", "quantity": "-1"],
["id": "8", "sellingPrice": "500", "quantity": "79"]]
*/
print("___________________")
var remainingBalanceDesriedValue = 420
myArray = myArray.map { (dict: [String: String]) -> [String: String] in
var copyDict = dict
copyDict["remaining_balance"] = "\(remainingBalanceDesriedValue)"
remainingBalanceDesriedValue = (remainingBalanceDesriedValue == 420) ? 499 : (remainingBalanceDesriedValue == 499) ? 500 : 420
return copyDict
}
print(myArray)
/*
[["sellingPrice": "520", "quantity": "15", "id": "3", "remaining_balance": "420"],
["sellingPrice": "499", "quantity": "-1", "id": "5", "remaining_balance": "499"],
["sellingPrice": "500", "quantity": "79", "id": "8", "remaining_balance": "500"]]
*/
Let's assume you have an array of dictionaries like so:
var arrayOfDictionaries = [
[
"id": 3,
"sellingPrice": 520,
"quantity": 15
]
]
It is important that arrayOfDictionaries is not a let constant, otherwise it is considered immutable and you can not call append on it.
Now you init a new dictionary like:
let newDictionary = [
"id": 10,
"remaining_balance": 420,
"quantity": 15
]
Now add the newDictionary like
arrayOfDictionaries.append(newDictionary)
If the order is important
If the order is important there are a couple of ways to go about that.
When calling append the new value (in this case the new dictionary) will always be inserted at the bottom of the array.
If for some reason you can not call append in the correct order you could use insert, which inserts your dictionary at a specific position.
Yet another way is to append the values wildly and after you are done, call sort on the array.
Improvement Tips
Notice that for the values I did not use strings, as you only have numbers like "id" : 30.
Also, if you want the second key to be called remaining_balance you should call the first key selling_price instead of sellingPrice. Because of conistency.
Alternative approach
As far as I have understood you are trying to implement some software that is responsibly for selling some products.
I think you are tackling this problem from a completely wrong side.
I think you should read about database relationships. Selling products actually is a very common problem.
Maybe this will help you. I would offer a possible solution myself, but I think this misses the point of your question.
If you decide to use the database approach, you won't necessarily have to use a database. You can take the approach and implement it using simple structs/classes/arrays.
I noticed this question lacks an extension answer, yes.. I'm gonna be that guy, so here it is. This could be made more generic by supporting other types of dictionaries, feel free to pitch in ;)
Inspiration from #eason's answer.
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
var array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
extension Array where Element == [String: String] {
enum UniquingKeysStrategy {
case old
case new
}
mutating func merge(with target: Array<Element>, uniquingKeysWith: UniquingKeysStrategy = .new) {
self = self.merged(with: target)
}
func merged(with target: Array<Element>, uniquingKeysWith strategy: UniquingKeysStrategy = .new) -> Array<Element> {
let base = self.count > target.count ? self : target
let data = self.count > target.count ? target : self
return data.enumerated().reduce(into: base, {
result, data in
result[data.offset]
.merge(data.element, uniquingKeysWith: {
old, new in
if strategy == .new { return new }
return old
})
})
}
}
let mergedArrays = newKV.merged(with: array, uniquingKeysWith: .old)
array.merge(with: newKV)
Happy Coding :)
I'm trying to download and filter json data. After filtering json data, i printed that filtered data which is working fine. But when i try to append that data to string type of array its gets crash and error is :-
Could not cast value of type '__NSArrayI' (0x106d27d88) to 'NSString'
(0x107be3c40).
code sample and output
cast that productName as array of string like this. [String]
let productName = jsonObj?.value(forKey: "name") as! [String]
then follow this links
1) https://www.hackingwithswift.com/example-code/arrays/how-to-join-an-array-of-strings-into-a-single-string
2) How do I convert a Swift Array to a String?
Example
let productName1 = ["1", "2", "3"]
var arrayForName1 = [String]()
arrayForName1 = ["name"]
let str = productName1.joined(separator: "")
// ["name", "123"]
// or
let str1 = productName1.joined(separator: ", ")
// ["name", "1, 2, 3"]
arrayForName1.append(str)
Your productName is an array and you are casting it to String so that causes your problem. You have two options to fix this base:
Validate your productName array and find the correct index of the actual string to append to your arrayForName1 array. So your code will look like
arrayForName1.append(productName[0])
If your productName is an array of string and you want to add all of them to arrayForName1, simply use this code
arrayForName1 += productName
Into Your json data Array are give with any Parameter (like: Number = ["1", "2", "3"] )
var Number1:String? = ""
var NumberList:[String] = []
if let Number_from = anItem["Number"] as? String {
self.Number1 = Number_from
self.NumberList.append(self.Number1!)
} else {
self.NumberList.append("Not Available")
}
I want to initialise a list of parameters in Swift by reading text files containing eight parameter values and preserve the parameters in the same order they are read from file. Once initialised parameter values do not change. Ideally they should be accessed efficiently - and be especially clear for anyone maintaining code further down the track.
In the Playground example (below) parameter values are stored in an Array of Arrays of Strings. Raw values from the Enumeration are then used as a set of indices to address the Array. Initially I thought of using Enumeration to store parameter values as raw values to be addressed using either the parameter name or a numerical index. But from this answer I cannot see a way to assign parameter values directly to member names. In fact I'm starting to doubt whether I should be using an enumeration at all.
Can anyone offer a better way to do this ?
(This probably sounds naive as I've never used a Swift Enumeration before).
enum MapParameters: Int {
case midiChannel = 0,
sizeOfRepeatingMapPattern = 1,
firstMIDIKey = 2,
lastMIDIKey = 3,
middleKey = 4,
referenceMIDIKey = 5,
referenceFrequency = 6,
keysPerFormalOctave = 7
}
let sourceArray = ["5", "12", "0", "127", "60", "69", "440.0", "12"]
let mapIndex = MapParameters.referenceFrequency //referenceFrequency
let i = mapIndex.rawValue // 6
let parameterValue = sourceArray[i] // "440.0"
Using MapParameters enum for making what's the meaning of each index (making it more readable) of sourceArray is legal, however, that's should be valid iff the sourceArray.count is equals to 8 and its sorting is always the same.
You can use it as:
enum MapParameters: Int {
case midiChannel = 0,
sizeOfRepeatingMapPattern = 1,
firstMIDIKey = 2,
lastMIDIKey = 3,
middleKey = 4,
referenceMIDIKey = 5,
referenceFrequency = 6,
keysPerFormalOctave = 7
}
let sourceArray = ["5", "12", "0", "127", "60", "69", "440.0", "12"]
let firstMIDKeyFromSource = sourceArray[MapParameters.firstMIDIKey.rawValue] // 0
let middleKeyFromSource = sourceArray[MapParameters.middleKey.rawValue] // 60
In fact, I find the code snippet above code smell bad; There are alternatives that should be more optimized, such as: Receiving these values as a Dictionary, OR if -somehow- you have to get them as an array, you might want to map
them via a simple model, similar to:
struct MappedParameters {
// you might want to give them initial values
// or you can make them as optionals
var midiChannel = ""
var sizeOfRepeatingMapPattern = ""
var firstMIDIKey = ""
var lastMIDIKey = ""
var middleKey = ""
var referenceMIDIKey = ""
var referenceFrequency = ""
var keysPerFormalOctave = ""
init(sourceArray: [String]) {
if sourceArray.count != 8 {
fatalError("ERROR: sourceArray.count is NOT 8")
}
midiChannel = sourceArray[0]
sizeOfRepeatingMapPattern = sourceArray[1]
firstMIDIKey = sourceArray[2]
lastMIDIKey = sourceArray[3]
middleKey = sourceArray[4]
referenceMIDIKey = sourceArray[5]
referenceFrequency = sourceArray[6]
keysPerFormalOctave = sourceArray[7]
}
}
Usage:
Somewhere in your code you should implement:
let sourceArray = ["5", "12", "0", "127", "60", "69", "440.0", "12"]
let sourceMapper = MappedParameters(sourceArray: sourceArray)
and simply, use sourceMapper as:
print(sourceMapper.firstMIDIKey) // 0
print(sourceMapper.middleKey) // 60
Hope this helped.
An alternative to #Ahmad F's answer could be to use static members
struct MapParameters {
static let midiChannel = 0
static let sizeOfRepeatingMapPattern = 1
static let firstMIDIKey = 2
static let lastMIDIKey = 3
static let middleKey = 4
static let referenceMIDIKey = 5
static let referenceFrequency = 6
static let keysPerFormalOctave = 7
}
let sourceArray = ["5", "12", "0", "127", "60", "69", "440.0", "12"]
let parameterValue = sourceArray[MapParameters.referenceFrequency]