Hi, regarding solution for <https://leetcode.com/p...
# getting-started
e
Hi, regarding solution for https://leetcode.com/problems/image-smoother/ problem
Copy code
class Solution {
    fun imageSmoother(image: Array<IntArray>): Array<IntArray> {
        val neighborsOf = { i: Int, j: Int ->
            sequence {
                for (di in -1..1)
                    for (dj in -1..1)
                        image.getOrNull(i + di)
                            ?.getOrNull(j + dj)
                            ?.let { yield(it) }
            }
        }

        return Array(image.size) { i ->
            IntArray(image[0].size) { j ->
                val neighbors= neighborsOf(i, j)
                neighbors.sum() / neighbors.count()
            }
        }
    }
}
I'm considering denesting the
neighborsOf
. Here's the nested block I'm referring to:
Copy code
val neighborsOf = { i: Int, j: Int ->
  sequence {
    for (di in -1..1)
      for (dj in -1..1)
        image.getOrNull(i + di)
          ?.getOrNull(j + dj)
          ?.let { yield(it) }
  }
}
Is denesting even worth it in this context? Or is the current form already clear enough?
I'm only concerned with readability here. Performance, reusability, or extensibility aren't priorities in this case
c
?.let
is for non-important side effects of an operation, this should probably be a regular
if
to improve readability Also, the return type isn't used, so if you really want to use a scope function here, it should be
?.also
👍 1
Maybe something like this?
Copy code
val d  = sequenceOf(-1, 0, 1)

fun neighborsCoordinatesOf(i: Int, j: Int): Sequence<Pair<Int, Int>> =
	sequenceOf(i to j)
		.flatMap { (x, y) -> d.map { x to (y + it) } }
		.flatMap { (x, y) -> d.map { (x + it) to y } }

fun neighborsOf(i: Int, j: Int) =
	neighborsCoordinatesOf(i, j)
		.map { (x, y) -> image.getOrNull(x, y) }
👍 1
I think this version returns more elements than yours 🤔 Anyway the interesting thing is using
.flatMap
to avoid nesting
👍 1
e
Thanks, I'll look into .flatMap usage. First time I see
?.let is for non-important side effects
- is there an article or doc with reasoning around this?
j
For me,
let
is just a tool to do concatenative programming. I use it that way all the time and haven't seen any advice to the contrary until now. Also, as an aside, in real life a
Array<IntArray>
would be a terrible way to work with image data. A
ByteArray
if you want raw pixel data access would make more sense in terms of efficiency, or at least RAM usage. Gotta fill the spec LeetCode gives you, though.
💯 1
k
"is for non-important side effects" would be a perfect description for
?.also
, but not for
?.let
.
c
Sorry, indeed.
?.let
is non-important data conversions. My point was, there shouldn't really be a
yield
in a
let
j
I can understand that opinion, though I'd probably use it anyways. I probably way overuse
let
.