I’ve got a `Sequence` of `String`s and apply lots ...
# codereview
m
I’ve got a
Sequence
of `String`s and apply lots of mapping operations. Now, after these mappings I want to access the original index in the sequence. However, if I use
mapIndexedValue
then I need to change each mapping operation implementation. Instead, is it recommended to declare and use something like this (not tested) so that we can continue to use the same transforms as before? Side note: is there a danger in using mutable values like this?
Copy code
data class IndexedMutableValue<T>(val index: Int, var value: T)

fun <T> Sequence<T>.withIndexedMutableValue(): Sequence<IndexedMutableValue<T>> =
    mapIndexed { index, t -> 
        IndexedMutableValue(index, t)
    }

fun <T> Sequence<IndexedMutableValue<T>>.mapIndexedMutable(transform: (T) -> T): Sequence<IndexedMutableValue<T>> {
    forEach { it.value = transform(it.value) }
    return this
}

fun <T> Sequence<IndexedMutableValue<T>>.mapIndexedMutableNotNull(transform: (T) -> T?): Sequence<IndexedMutableValue<T>> {
    forEach { it.value = transform(it.value) ?: return@forEach }
    return this
}

fun <T> Sequence<IndexedMutableValue<T>>.flatMapIndexedMutable(transform: (T) -> Sequence<T>): Sequence<IndexedMutableValue<T>> {
    return sequence {
        forEach { indexedValue ->
            transform(indexedValue.value).forEach { newValue ->
                yield(indexedValue.copy(value = newValue))
            }
        }
    }
}
e
I'd go for something more like
Copy code
inline fun <T, R> Sequence<IndexedValue<T>>.mapValues(
    crossinline transform: (T) -> R
): Sequence<IndexedValue<R>> = map { (i, v) -> IndexedValue(i, transform(v)) }

inline fun <T, R : Any> Sequence<IndexedValue<T>>.mapValuesNotNull(
    crossinline transform: (T) -> R?
): Sequence<IndexedValue<R>> = mapNotNull { (i, v) ->
    transform(v)?.let { IndexedValue(i, it) }
}

inline fun <T, R> Sequence<IndexedValue<T>>.flatMapValues(
    crossinline transform: (T) -> Sequence<R>
): Sequence<IndexedValue<R>> = flatMap { (i, v) ->
    transform(v).map { IndexedValue(i, it) }
}
👍 1
this frees you from being restricted to
transform: (T) -> T
and immutable behaves more predictably if anybody does something like
Copy code
.withIndex()
.onEach { logLater(it) }
.mapValue { transform(it) }
m
I agree, that’s nicer and safer, thanks!