Hot to declare an empty Map/dictionary? - f#

I would like to initialize a recursive function with a Map. To declare a read-only dictionary with value we can do:
let dictionary1 = dict [ (1, "a"); (2, "b"); (3, "c") ]
Try it online!
Now, I would like to create an empty dictionary. How to achieve that?
I am looking fo something like:
let dictionary1 = {} // <- ok this is js
let (stuff, dictionary2) = parseRec("whatever", dictionary1)

You can do:
let dictionary1 = dict []
for elem in dictionary1 do
printfn "Key: %d Value: %s" elem.Key elem.Value
and that gives you an empty dictionary.
The printfn usage reveals to the type inference engine the correct types of key and value.
If you want to be explicit then you can specify the types in several ways:
let dictionary1 = dict Seq.empty<int * string>
let dictionary1 = dict ([] : (int * string) list)
let dictionary1 = dict [] : System.Collections.Generic.IDictionary<int, string>
let dictionary1 : System.Collections.Generic.IDictionary<int, string> = dict []

Since you ask for Map/Dictionary, here is two other solutions for Map:
let dictionary1 : Map<int, string> = Map.empty
let dictionary1 = Map<int, string> []
source

If you need a .NET Dictionary, you can use a .net Dictionary:
let dictionary1 = new System.Collections.Generic.Dictionary<int, string>()

Related

can i sum of values that has the same key in dictionary

I have a dictionary like this :
let dic: KeyValuePairs = ["foo":2,"bar":3,"bat":5, "foo":5,"bat":7,"bar":5]
I want the sum of values that has the same key.
The output should look like this:
["foo":7, "bar":8, "bat":12]
KeyValuePairs responds to reduce so you can do this
let dic: KeyValuePairs = ["foo":2,"bar":3,"bat":5, "foo":5,"bat":7,"bar":5]
let result : [String:Int] = dic.reduce(into: [:]) { (current, new) in
current[new.key] = new.value + (current[new.key] ?? 0)
}

How to convert JObject into JArray in f#

I want to convert this tablesinJson into JArray and loop through it.
let tablesInJson = (JArray)jsonModel["tables"];
Something simmilar as we do in C#
let json = "{
"table": [{
"boolean": true,
"null": null,
"number": 123,
"string": "Hello World"
}]
}"
let ConvertFoo (jsonModel : JObject) (TableInfo : TableInfo list) =
let tablesinJson = jsonModel.["tables"]
//convert tablesinJson into JArray and loop through it
//let tablesInJson = (JArray)jsonModel["tables"]; something like this
printfn "%O" jsonModel.["tables"]
printfn "%O" sqlTableInfos
let _json= JObject.Parse(json)
let list = [TableName "one" ; ColumnName "table"]
ConvertFoo _json list
A minimal example that iterates over all the objects in the table field and prints the string field is:
open Newtonsoft.Json.Linq
let parsed = JObject.Parse(json)
let tables = parsed.["table"] :?> JArray
for table in tables do
let value = table.["string"] :?> JValue
printfn "%O" value
As mentioned in the comments, you need to use the :?> operator to cast the object to JArray (so that you can iterate over it using for) or to JValue (so that you can access the value).
It might be worth noting that you could do the same thing using the Json type provider from F# Data and you would avoid all the casting because the type provider infers the types and exposes all nested data as members:
open FSharp.Data
[<Literal>]
let json = """{ "table": [ {"boolean": true, "null": null,
"number": 123,"string": "Hello World" }]}"""
type Parser = JsonProvider<json>
let parsed = Parser.Load(json)
for table in parsed.Table do
printfn "%s" table.String

Swift: Get all key value pairs from a String

I have a String which has many key value pairs appended by a & sign. i.e: params = key1=Hello&key2=Hello World&key3=Hi Hello
Is there a way to extract the values just by passing the keys present in the string? For example I want to extract the value of key1, key2, key3.
let string = "key1=Hello&key2=Hello World&key3=Hi Hello"
let components = string.components(separatedBy: "&")
var dictionary: [String : String] = [:]
for component in components{
let pair = component.components(separatedBy: "=")
dictionary[pair[0]] = pair[1]
}
And in dictionary you will get your key-value pairs.
You can use URLComponents and URLQueryItem anyway by creating a dummy URL
let params = "key1=Hello&key2=Hello World&key3=Hi Hello"
if let components = URLComponents(string: "http://dummy.com/path?" + params.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!),
let queryItems = components.queryItems {
let arrayOfValues = queryItems.flatMap{ $0.value }
print(arrayOfValues)
}
see also Best way to parse URL string to get values for keys?
let params = "key1=Hello&key2=Hello World&key3=Hi Hello"
let sepparated = params.components(separatedBy: CharacterSet(charactersIn: "&="))
let keys = sepparated.enumerated().filter{$0.0 % 2 == 0}
print (keys) // [(offset: 0, element: "key1"), (offset: 2, element: "key2"), (offset: 4, element: "key3")]

How to combine two complex Dictionaries

I'm curious how to combine two dictionaries which one of them contains key with array or another dictionary as value.
for simple combining e.g.
var dict1 = ["bbb":"dict1",
"her": "dict1"]
let dict2 = ["aaa":"dict2",
"her": "doct2",
"bob": "doct2"]
dict1 += dict2 // result is as I expected
func += <K, V> (inout left: [K:V], right: [K:V]) {
for (k, v) in right {
left.updateValue(v, forKey: k)
}
}
But problem rise when I want to combine more complex dictionary e.g.
var dict1 = ["bbb":"dict1",
"her": "dict1"]
let complexDict2 = ["aaa":"dict2",
"her": "dict2",
"arr": ["one", "two"]]
dict1 += complexDict2 // in here method which override '+=' operator for dictionaries does not work anymore...
My question is whether you guys have a proved way to combine more complex dictionaries?
Upadate
My expected result from combining dict1 and complexDict2 is :
let resultDict = ["aaa":"dict1",
"aaa":"dict2",
"her": "dict2",
"arr": ["one", "two"]]
The issue here lies in the types of dict1 and complexDict2.
dict1 is inferred to have type [String : String], whereas complexDict2 is inferred to have type [String : Any].
Your code works just fine, if you explicitly specify a type annotation on dict1:
var dict1: [String : Any] = [
"aaa":"dict1",
"her": "dict1"
]

How to convert dictionary to array

I want to convert my dictionary to an array, by showing each [String : Int] of the dictionary as a string in the array.
For example:
    
var myDict: [String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
    
I'm aware of myDict.keys.array and myDict.values.array, but I want them to show up in an array together. Here's what I mean:
    
var myDictConvertedToArray = ["attack 1", "defend 5", "block 12"]
You can use a for loop to iterate through the dictionary key/value pairs to construct your array:
var myDict: [String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
var arr = [String]()
for (key, value) in myDict {
arr.append("\(key) \(value)")
}
Note: Dictionaries are unordered, so the order of your array might not be what you expect.
In Swift 2 and later, this also can be done with map:
let arr = myDict.map { "\($0) \($1)" }
This can also be written as:
let arr = myDict.map { "\($0.key) \($0.value)" }
which is clearer if not as short.
The general case for creating an array out of ONLY VALUES of a dictionary in Swift 3 is (I assume it also works in older versions of swift):
let arrayFromDic = Array(dic.values.map{ $0 })
Example:
let dic = ["1":"a", "2":"b","3":"c"]
let ps = Array(dic.values.map{ $0 })
print("\(ps)")
for p in ps {
print("\(p)")
}
If you like concise code and prefer a functional approach, you can use the map method executed on the keys collection:
let array = Array(myDict.keys.map { "\($0) \(myDict[$0]!)" })
or, as suggested by #vacawama:
let array = myDict.keys.array.map { "\($0) \(myDict[$0]!)" }
which is functionally equivalent
With Swift 5
var myDict:[String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
let arrayValues = myDict.values.map({$0})
let arrayKeys = myDict.keys.map({$0})
You will have to go through and construct a new array yourself from the keys and the values.
Have a look at 's swift array documentation:
You can add a new item to the end of an array by calling the array’s
append(_:) method:
Try this:
var myDict:[String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
var dictArray: [String] = []
for (k, v) in myDict {
dictArray.append("\(k) \(v)")
}
Have a look at What's the cleanest way of applying map() to a dictionary in Swift? if you're using Swift 2.0:

Resources