From c818a628341362edff240390ca62013a48df32a3 Mon Sep 17 00:00:00 2001 From: Sancarn Date: Mon, 8 Jul 2024 01:16:28 +0100 Subject: [PATCH] Add `stdEnumerator::CreateFromDictionaryEx` and `stdEnumerator#groupByEx` --- changelog.md | 4 +++- src/stdEnumerator.cls | 46 ++++++++++++++++++++++++++++++++++++++++--- src/stdLambda.cls | 2 +- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index e05d9e3..66a2050 100644 --- a/changelog.md +++ b/changelog.md @@ -307,4 +307,6 @@ Before `08/07/2021` a change log was not kept. We have retrospectively gone back - 2024-07-01 `stdAcc` FIX - Fixed bug where numerous states weren't being correctly identified. - 2024-07-04 `stdWindow` FEATURE - Added `stdWindow::Create()`, allowing users to create windows, and `stdWindow::CreateHighlightRect()` to create a window with a highlight rectangle. Also added `stdWindow#hDCClient` to get the hDC of the client area of the window. - 2024-07-04 `stdWindow` FIX - Fixedd bug where `stdWindow#Visible` would focus the window it changed visibility of. This has been fixed. -- 2024-07-04 `stdJSON` FIX - Fixed bug where `stdJSON` wasn't correctly handling strings with `"` in them. \ No newline at end of file +- 2024-07-04 `stdJSON` FIX - Fixed bug where `stdJSON` wasn't correctly handling strings with `"` in them. +- 2024-07-08 `stdEnumerator` FEATURE - `stdEnumerator::CreateFromDictionaryEx` added. Translates a dictionary to a Enumerator of dictionaries with key and value properties. Additionally added `stdEnumerator#groupByEx` which utilises the above. +- 2024-07-08 `stdLambda` FIX - Removed `key` from the dictionary checks in `stdLambda#stdCallByName`. Shouldn't be a breaking change, because `key` isn't a method on type `Dictionary`. \ No newline at end of file diff --git a/src/stdEnumerator.cls b/src/stdEnumerator.cls index 3953ce5..8be532a 100644 --- a/src/stdEnumerator.cls +++ b/src/stdEnumerator.cls @@ -265,9 +265,32 @@ End Function '@param iMaxLength - Maximum length of enumerator. The enumerator will refuse to go beyond this number of items. Used in order to prevent runaway processes. '@returns - An enumerator representing the dictionary data '@TODO: Finish function - requires key handling. Might be a bit of a pain as it requires refactoring to work with collection keys among other things. -Private Function CreateFromDictionary(ByVal o as object, optional byval iMaxLength as long = 1000000) as stdEnumerator - set CreateFromDictionary = new stdEnumerator - 'Call CreateFromDictionary.protInit(EnumeratorType.FromDictionary,iMaxLength,o) +'may not be needed given we have `CreateFromDictionaryEx`, but it would be far more performant. +Private Function CreateFromDictionary(ByVal dictionary as object, optional byval iMaxLength as long = 1000000) as stdEnumerator + +End Function + +'Translates a dictionary to a Enumerator of dictionaries with key and value properties. +'@constructor +'@param dictionary - The dictionary to create the enumerator from. +'@param iMaxLength - Maximum length of enumerator. The enumerator will refuse to go beyond this number of items. Used in order to prevent runaway processes. +'@returns stdEnumerator>> - An enumerator representing the dictionary data +'@example ``` +'set dict = stdEnumerator.CreateFromArray(Array(1,2,3,2,2,1,3,2,3,1,2,3)).groupBy(stdLambda.Create("$1")) +'set dictEx = stdEnumerator.CreateFromDictionaryEx(dict).forEach(stdLambda.Create("let $1.value = $1.value.count")).sort(stdLambda.Create("$1.count")).last +'``` +Public Function CreateFromDictionaryEx(ByVal dictionary as object) as stdEnumerator + Dim keys as variant: keys = dictionary.keys() + Dim items as variant: items = dictionary.items() + Dim rows as collection: set rows = new collection + For i = 0 to ubound(keys) + Dim row as object: set row = CreateObject("Scripting.Dictionary") + row.CompareMode = vbTextCompare + row.add "key", keys(i) + row.add "value", items(i) + rows.add row + next + set CreateFromDictionaryEx = stdEnumerator.CreateFromIEnumVariant(rows) End Function 'Initialse the stdEnumerator @@ -955,6 +978,23 @@ Public Function groupBy(ByVal cb as stdICallable) as object set groupBy = oRet End Function +'Returns a new enumerator containing groups from groupBy, with the key and item properties added +'@param cb as stdICallable<(element: Variant)=>Variant> - The callable which when run on an element returns the key to group by +'@returns stdEnumerator>> - Enumerator containing grouped data +'@example ``` +'Dim e as stdEnumerator: set e = stdEnumerator.CreateFromArray(Array(1,2,3,2,2,1,3,2,3,1,2,3)) +'Debug.Print e.groupByEx(stdLambda.Create("$1")).Map(stdLambda.Create("$1.key & ""-"" & $1.value.length")).Join(";") +'``` +'@example ``` +''Get the largest count +'Dim e as stdEnumerator: set e = stdEnumerator.CreateFromArray(Array(1,2,3,2,2,1,3,2,3,1,2,3)) +'Debug.Print e.groupByEx(stdLambda.Create("$1")).Sort(stdLambda.Create("-1 * $1.value.length")).Item(1)("key") +'``` +Public Function groupByEx(ByVal cb as stdICallable) as stdEnumerator + Dim groups as object: set groups = groupBy(cb) + set groupByEx = CreateFromDictionaryEx(groups) +End Function + 'Obtains the maximum value from the enumerator. If a callback is given the item which returns the largest value from the callback is returned. '@param cb as stdICallable<(element: Variant)=>Variant> - If callback given, callback to obtain max value of. Else max of the elements values are found. '@returns - Value containing max data diff --git a/src/stdLambda.cls b/src/stdLambda.cls index 31789b8..2584629 100644 --- a/src/stdLambda.cls +++ b/src/stdLambda.cls @@ -1344,7 +1344,7 @@ Private Function stdCallByName(ByRef obj As Object, ByVal funcName As String, By 'If Dictionary and If TypeName(obj) = "Dictionary" Then Select Case funcName - Case "add", "exists", "items", "keys", "remove", "removeall", "comparemode", "count", "item", "key" + Case "add", "exists", "items", "keys", "remove", "removeall", "comparemode", "count", "item" 'These methods already exist on dictionary, do not override Case Else Select Case callerType