Mark
06/04/2022, 4:30 AMfun <T, R> Iterable<T>.singleOrNullBy(transform: (T) -> R): R? {
    if (this is Collection && this.isEmpty()) return null
    return asSequence()
        .map(transform)
        .zipWithNext()
        .map { (a, b) -> if (a == b) a else null } // important we don't use mapNotNull here
        .distinct()
        .singleOrNull()
}ephemient
06/04/2022, 5:38 AMinline fun <T, R> Iterable<T>.singleOrNullBy(transform: (T) -> R): R? {
    return fold(null) { acc: R?, item ->
        val value = transform(item)
        if (acc == null || acc == value) value else return null
    }
}ephemient
06/04/2022, 5:45 AMnullinline fun <T, R> Iterable<T>.singleOrNullBy(transform: (T) -> R): R? {
    val nothing = Any()
    return fold(nothing) { acc: Any?, item ->
        val value = transform(item)
        if (acc === nothing || acc == value) value else return null
    }.takeIf { it !== nothing } as R?
}ephemient
06/04/2022, 5:47 AMsingleOfOrNullMark
06/04/2022, 6:57 AMIteratorinline fun <T, R> Iterable<T>.singleOfOrNull(transform: (T) -> R): R? {
    // let's see if we can avoid creating the iterator
    if (this is Collection) {
        if (this.isEmpty()) return null
        if (this is List && size == 1) {
            return transform(this[0])
        }
    }
    return this.iterator().singleOfOrNull(transform)
}
inline fun <T, R> Iterator<T>.singleOfOrNull(transform: (T) -> R): R? {
    if (!this.hasNext()) {
        return null
    }
    val firstItemTransformed = transform(this.next())
    if (!this.hasNext()) {
        return firstItemTransformed
    }
    this.forEach { item ->
        if (transform(item) != firstItemTransformed) {
            return null
        }
    }
    return firstItemTransformed
}Mark
06/04/2022, 7:13 AMinline fun <T, R> Iterable<T>.singleOfOrNull(noinline transform: (T) -> R): R? {
    // let's see if we can avoid creating the sequence
    if (this is Collection) {
        if (this.isEmpty()) return null
        if (this is List && this.size == 1) {
            return transform(this[0])
        }
    }
    return this.asSequence().map(transform).distinct().singleOrNull()
}singleDistinctOfOrNullephemient
06/04/2022, 9:58 AMSequenceinlineephemient
06/04/2022, 10:05 AMinline fun <T, R> Iterable<T>.singleOfOrNull(transform: (T) -> R): R? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    val single = transform(iterator.next())
    for (item in iterator) if (transform(item) != single) return null
    return single
}ephemient
06/04/2022, 10:16 AMval list = CopyOnWriteArrayList(listOf(1))
thread { list.add(2); list.add(3); list.remove(1) }
list.singleOfOrNull { it }2list == listOf(2)Mark
06/04/2022, 1:17 PMIteratorephemient
06/04/2022, 1:18 PM.forEachforMark
06/04/2022, 1:27 PMinline fun <T, R> Iterable<T>.singleDistinctOfOrNull(transform: (T) -> R): R? {
    // let's see if we can avoid creating the iterator
    if (this is Collection && this.isEmpty()) {
        return null
    }
    val iterator = this.iterator()
    if (!iterator.hasNext()) {
        return null
    }
    val firstItemTransformed = transform(iterator.next())
    if (!iterator.hasNext()) {
        return firstItemTransformed
    }
    for (item in iterator) if (transform(item) != firstItemTransformed) return null
    return firstItemTransformed
}ephemient
06/04/2022, 1:28 PMis List.singleOrNull()iterator()Mark
06/04/2022, 1:31 PMsingleOrNull()Iterator