From c675259737becea3591f5ff0b81559322843a226 Mon Sep 17 00:00:00 2001 From: omaus Date: Sun, 26 Mar 2023 23:20:48 +0200 Subject: [PATCH 1/2] Add `Dictionary` functions `tryGetValue`, `getValue`, `tryGetString`, `length`, `copyRecursive`. --- src/FSharpAux/Dictionary.fs | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/FSharpAux/Dictionary.fs b/src/FSharpAux/Dictionary.fs index 3aa9f6b..3e31d56 100644 --- a/src/FSharpAux/Dictionary.fs +++ b/src/FSharpAux/Dictionary.fs @@ -115,6 +115,52 @@ module Dictionary = | true -> Some table.[key] | false -> None + /// + /// Returns the value of the given key if present in the given Dictionary. Else returns None. + /// + let tryGetValue k (dict : Dictionary<'K,'V>) = + let b,v = dict.TryGetValue(k) + // Only get value if + if b then Some v + else + None + + /// + /// Returns the value to the key k if it is bound, else fails. + /// + let getValue k (dict : Dictionary<'K,'V>) = + try + dict.Item k + with + | _ -> failwithf "Key %O is not present in Dictionary %O." k dict + + /// + /// Returns the trimmed string of the given key if present in the given Dictionary. Else returns None. + /// + let tryGetString k (dict : Dictionary<'K,string>) = + let b,v = dict.TryGetValue(k) + // Only get value if + if b && v.Trim() <> "" + then + v.Trim() |> Some + else + None + + /// + /// Returns the number of key/value pairs contained in the given Dictionary. + /// + let length (dict : Dictionary<'K,'V>) = + dict.Count + + /// + /// Applies an inner copy function to all values in a given Dictionary and returns a copy of the Dictionary. + /// + let copyRecursive (innerCopyF : 'V -> 'V) (dict : Dictionary<'K,'V>) = + let newDict = Dictionary<'K,'V>() + for kv in dict do + newDict.Add(kv.Key,innerCopyF kv.Value) + newDict + // /// Folds over the bindings in the dictionary // /// The function to update the state given the input key/value pairs. From 7a9395d893cf3febc7ed2bb68e8d0478701c2190 Mon Sep 17 00:00:00 2001 From: omaus Date: Sun, 26 Mar 2023 23:20:59 +0200 Subject: [PATCH 2/2] Add `Dictionary` unit tests --- tests/FSharpAux.Tests/DictionaryTests.fs | 63 ++++++++++++++++++++ tests/FSharpAux.Tests/FSharpAux.Tests.fsproj | 1 + 2 files changed, 64 insertions(+) create mode 100644 tests/FSharpAux.Tests/DictionaryTests.fs diff --git a/tests/FSharpAux.Tests/DictionaryTests.fs b/tests/FSharpAux.Tests/DictionaryTests.fs new file mode 100644 index 0000000..6da3dc8 --- /dev/null +++ b/tests/FSharpAux.Tests/DictionaryTests.fs @@ -0,0 +1,63 @@ +module DictionaryTests + +open Expecto +open FSharpAux +open System.Collections.Generic + + +let testDic1 = new Dictionary() +testDic1.Add(1, "Hello") +testDic1.Add(2, "World") +testDic1.Add(3, " World ") +let testDicRec = new Dictionary>() +let testDicRecInner = new Dictionary() +testDicRecInner.Add(1, "inner string") +testDicRec.Add(1, testDicRecInner) + + +[] +let dictTests = + testList "DictionaryTests" [ + testList "Dictionary.tryGetValue" [ + testCase "Is Some" <| fun _ -> + Expect.isSome (Dictionary.tryGetValue 2 testDic1) "Is None" + testCase "Is None when expected" <| fun _ -> + Expect.isNone (Dictionary.tryGetValue 4 testDic1) "Is Some" + testCase "Returns correct value" <| fun _ -> + let res = Dictionary.tryGetValue 2 testDic1 + Expect.equal res.Value "World" "Did not return correct value" + ] + testList "Dictionary.tryGetString" [ + testCase "Is Some" <| fun _ -> + Expect.isSome (Dictionary.tryGetString 2 testDic1) "Is None" + testCase "Is None when expected" <| fun _ -> + Expect.isNone (Dictionary.tryGetString 4 testDic1) "Is Some" + testCase "Returns correct string" <| fun _ -> + let res = Dictionary.tryGetString 2 testDic1 + Expect.equal res.Value "World" "Did not return correct string" + testCase "Returns correct string, trimmed" <| fun _ -> + let res = Dictionary.tryGetString 3 testDic1 + Expect.equal res.Value "World" "Did not return correctly trimmed string" + ] + testList "Dictionary.getValue" [ + testCase "Throws when expected" <| fun _ -> + Expect.throws (fun _ -> Dictionary.getValue 4 testDic1 |> ignore) "Did not throw though item does not exist" + testCase "Returns correct value" <| fun _ -> + let res = Dictionary.getValue 2 testDic1 + Expect.equal res "World" "Did not return correct value" + ] + testList "Dictionary.length" [ + testCase "Returns correct count" <| fun _ -> + let res = Dictionary.length testDic1 + Expect.equal res 3 "Returns incorrect count" + ] + testList "Dictionary.copyRecursive" [ + let testDicRecCopy = Dictionary.copyRecursive (Dictionary.copyRecursive id) testDicRec + testCase "Returns deep copy, check outer count" <| fun _ -> + Expect.equal testDicRecCopy.Count 1 "Copied Dictionary does not have correct outer count" + testCase "Returns deep copy, check inner count" <| fun _ -> + Expect.equal (testDicRecCopy.Item 1).Count 1 "Copied Dictionary does not have correct inner count" + testCase "Returns deep copy, check inner value" <| fun _ -> + Expect.equal ((testDicRecCopy.Item 1).Item 1) "inner string" "Copied Dictionary does not have correct inner count" + ] + ] \ No newline at end of file diff --git a/tests/FSharpAux.Tests/FSharpAux.Tests.fsproj b/tests/FSharpAux.Tests/FSharpAux.Tests.fsproj index d318b91..5086fe8 100644 --- a/tests/FSharpAux.Tests/FSharpAux.Tests.fsproj +++ b/tests/FSharpAux.Tests/FSharpAux.Tests.fsproj @@ -7,6 +7,7 @@ +