List Set Operations — Kotlin source
Compute the union, intersection, difference, or symmetric difference of two newline-separated lists. Deduped results with optional trim and case-insensitive matching. Runs entirely in your browser, with a shareable link.
This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.
// list-set-ops — union / intersection / difference / symmetric difference of
// two newline-separated lists. Kotlin port (canonical TS:
// src/lib/list-set-ops.ts; Go twin: cli/list-set-ops). HashSet is the
// membership set; trim defaults on like the TS `trim !== false`.
class ListSetOps private constructor() {
class SetOptions(val caseInsensitive: Boolean = false, val trim: Boolean = true)
companion object {
// Folded membership key: lowercase copy when case-insensitive, else the item.
private fun key(s: String, o: SetOptions) = if (o.caseInsensitive) s.lowercase() else s
// Split a newline list into a deduped list (first-seen casing kept).
fun parseList(input: String, o: SetOptions): List<String> {
if (input.isEmpty()) return emptyList() // empty input = no items
val seen = HashSet<String>()
return input.split('\n').mapNotNull { raw ->
var item = raw
if (o.trim) {
item = item.trim()
if (item.isEmpty()) return@mapNotNull null
}
if (seen.add(key(item, o))) item else null
}
}
// Compute a set op over two lists; the result is "\n"-joined.
fun setOps(a: String, b: String, op: String, o: SetOptions = SetOptions()): String {
val la = parseList(a, o)
val lb = parseList(b, o)
val ka = la.mapTo(HashSet()) { key(it, o) }
val kb = lb.mapTo(HashSet()) { key(it, o) }
val out = ArrayList<String>()
when (op) {
"union" -> { // every unique item, a then b
val seen = HashSet<String>()
for (s in la + lb) if (seen.add(key(s, o))) out.add(s)
}
"intersect" -> for (s in la) if (key(s, o) in kb) out.add(s)
"difference" -> for (s in la) if (key(s, o) !in kb) out.add(s)
"symmetricDifference" -> { // exactly one list, a-only then b-only
for (s in la) if (key(s, o) !in kb) out.add(s)
for (s in lb) if (key(s, o) !in ka) out.add(s)
}
} // unknown op -> ""
return out.joinToString("\n")
}
}
}
fun main() {
val a = "apple\nbanana\ncherry"
val b = "banana\ncherry\ndate"
println(ListSetOps.setOps(a, b, "union")) // apple\nbanana\ncherry\ndate
println(ListSetOps.setOps(a, b, "intersect")) // banana\ncherry
println(ListSetOps.setOps(a, b, "difference")) // apple
println(ListSetOps.setOps(a, b, "symmetricDifference")) // apple\ndate
// case-folded compare, first-seen original casing emitted
println(ListSetOps.setOps("HELLO", "hello", "intersect", ListSetOps.SetOptions(caseInsensitive = true))) // HELLO
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →