Array Intersection, Union, And Difference In Lucee CFML

Published: May 28, 2022

For the last week or so, I’ve had some extreme tunnel vision at work as I was barrelling towards a deadline to finish building a Mail Blasts feature for InVision. And, now that I’m done (crushing it), I need a little breather. As a fun code kata, I thought I might play around with calculating array interactions, unions, and differences in Lucee CFML This isn’t something that comes up often in my day-to-day work. But, it’s yet another opportunity to showcase the unyielding power of the Struct as Index pattern in ColdFusion.

Before we look at the code, I think it’s important to underscore that this is not an entirely generic solution. My approach makes some assumptions about how I want the collection logic to operate:

  • I’m ignoring duplicate entries in all cases – only the first unique item is collected.

  • I’m ignoring null / undefined entries in the collection.

  • I’m assuming that 3 (number) and "3" (string) are the same value. This is a crucial assumption in all of my algorithms because all three functions work by building-up an index internally. And, since all Struct keys in ColdFusion are Strings, 3 (number) and "3" (string) both values result in the same Struct key.

  • I’m assuming that A (uppercase) and a (lowercase) are the same value. This is because Struct keys are, by default, case-insensitive. As such, both values result in the same Struct key.

    ASIDE: ColdFusion 2021 includes case-sensitive Structs, which would get around this issue. But, it’s not something I was worried about.

These are the assumptions that work for me, your mileage may vary. With these assumptions, I am able to create algorithms that require relatively simple logic and can be accomplished with only a single iteration of each collection. Which, I think means this is O(n) performance? It’s been decades since I’ve thought about Big-O notation.

All three of my ColdFusion functions allow an optional Closure to be passed-in as the function that maps a given value to its Struct-key. This allows us to compare complex objects in a language that doesn’t naturally allow of complex object comparisons.

And, finally, all three of my ColdFusion functions use an Ordered Struct to collect the results. This allows the calculated collection to be generated from the index while maintaining the order in which the values were inspected. I mean, Structs are just kind of an amazing data structure!

With that said, let’s get to the algorithms.

use the triple-equals (===) operator for complex object memory comparisons in Lucee CFML. But, all of that would just be edge-case handling (in my opinion). That’s why algorithms like this – in a language like ColdFusion which is very flexible – are probably ones you want to write yourself for a specific application. That way, you can bake-in all the assumptions you want!

If nothing else, let’s all just observe how amazing the Struct data-type is. As much as Lists are the unsung heroes of ColdFusion, Structs are very much the loudly sung heroes of ColdFusion! Not a day goes by where I don’t use a Struct in a fun and exciting way to get the job done.

Want to use code from this post?
Check out the license.