Thank you for sharing Grr1337.
Hi Lee!
In my experience, you wouldn't typically construct a function which includes conditionals to test for variations in the data type of the supplied argument: since you are developing the program, you know ahead of time the data that will eventually be supplied to the function, and can therefore construct the function accordingly.
For example, I think it would be very rare to develop a program in which a function would process a data set in the form of an association list of dotted pairs, and subsequently process a list of lists in the same manner. The developer would likely decide ahead of time which data type is better suited to storing the required data and would develop the appropriate function accordingly.
I agree that this is an "uneffective" approach:
"Simplier" list construction, and then reconstruct that list, using a subfunction.
but I've tried constructing before a list like the expected (in the main program), without any need of such subfunction.
The problem was maintaining the code: writing new versions or similar codes(that use the same approach) - required a reminder-investigations of what I did back then (keeping off my concentration on the significant part).
So IMO the "KISS" principle for the main code is worthy for the cost of unnoticeable function slow-down.
I've forgot that this type of iteration is not effective - by mapping a function to the list I'm about to operate, when my intention is to construct a new list from scratch.
Hence should used
foreach instead (like I see in your example codes).
Also yeah, I could used the
if function instead of
cond (I've just built myself a habit to avoid
if and use
and / or / cond conditionals).
Your first suggested function processes
exactly like I'd wanted (construct a sublists in the
cdr - for each instance with the same key) :
(defun groupbykey
( lst
/ rtn tmp
) )
)
)
_$ (GroupByKey
'(("KeyA" "Info1Aa" "Info1Ba" "Info1Ca")("KeyB" "Info1Ab" "Info1Bb" "Info1Cb")("KeyC" "Info1")
("KeyA" "Info2Aa" "Info2Ba" "Info2Ca")("KeyB" "Info2Ab" "Info2Bb" "Info2Cb")("KeyC" "Info2")
)
)
(("KeyA" ("Info1Aa" "Info1Ba" "Info1Ca") ("Info2Aa" "Info2Ba" "Info2Ca")) ("KeyB" ("Info1Ab" "Info1Bb" "Info1Cb") ("Info2Ab" "Info2Bb" "Info2Cb")) ("KeyC" ("Info1") ("Info2")))
My result is not that clean:
(GroupByKeys
'(("KeyA" "Info1Aa" "Info1Ba" "Info1Ca")("KeyB" "Info1Ab" "Info1Bb" "Info1Cb")("KeyC" "Info1")
("KeyA" "Info2Aa" "Info2Ba" "Info2Ca")("KeyB" "Info2Ab" "Info2Bb" "Info2Cb")("KeyC" "Info2")
)
)
(("KeyA" "Info1Aa" "Info1Ba" "Info1Ca" "Info2Aa" "Info2Ba" "Info2Ca") ("KeyB" "Info1Ab" "Info1Bb" "Info1Cb" "Info2Ab" "Info2Bb" "Info2Cb") ("KeyC" "Info1" "Info2"))
Sort list before grouping them is recommended. No sort, the time's complexity is O(n2/2), sort and group is O(nLOGn).
I always thought that sorting is redundant and slows down the function, when its used for tasks other than.. sorting.
But with this benchmark you proved me wrong!