【问题标题】:Kotlin: Is there any way to iterate this as a Sequence?Kotlin:有没有办法把它作为一个序列来迭代?
【发布时间】:2019-09-22 21:19:13
【问题描述】:

我正在制作一个图像过滤器,我已经完成了这项工作,但我已经读过,对于大型集合,最好使用序列进行迭代,因为是 8k 图像,我想我会获得一些性能因为它使用Sequence<IntArray> 而不是Array<IntArray> 甚至Sequence<Sequence<Int>> 进行延迟初始化。我不知道这是否可能,我很困惑并试图为我学习这个新范式,而且我很难找到更容易理解这个概念的用法语法的材料。

这是一个尝试过的方法,但是一团糟,我不知道如何进行此操作,或者即使我也应该使用“newImage”作为序列。

val myPredicate = { array : IntArray -> !array.first() /*???*/ && !array.last() }
image.asSequence().forEach { array ->
    array.filter(myPredicate ) // ???
}

这是要转换的功能代码:

fun chunker(image : Array<IntArray>) : Array<IntArray> {
    val arrayRowSize = image.size
    val arrayColSize = image[0].size
    val newImage : Array<IntArray> by lazy {
        Array(arrayRowSize) { IntArray(arrayColSize) }
    }

    var kernel = IntArray(9)
    // to translate to a Sequence those two for loops
    for (row in 1 .. arrayRowSize - 2) {
        for (col in 1 .. arrayColSize - 2) {
            kernel = changer(row, col, kernel, image)
            newImage[row][col] = kernel[4]
        }
    }
    return newImage
}

【问题讨论】:

  • 混淆的来源之一是“过滤器”这个词的不同含义吗?根据称为“谓词”的选择功能,在列表和数据结构中,这意味着删除一些元素并保留其他元素。但在图像处理中,它意味着转换图像以创建不同的图像。您的工作代码执行后者,但我认为您的部分尝试是尝试创建前者……
  • 嗯......但我也忘了提到我正在使用灰度图像。而且我不应该从旧图像中创建新图像,而是经过过滤。过滤器将逐像素通过,不考虑板。

标签: kotlin sequence


【解决方案1】:

我已经读过,对于大型集合,最好使用序列进行迭代

您可能读到的是,给定一个像myCollection.filter(...).map(...).first(...) 这样的功能管道,使用Sequence 可以提高性能,主要有两个原因:

  1. 如果不需要,序列将不会处理所有元素(first() 和结尾可能使其在看到所有元素之前终止)
  2. 与常规集合不同,该序列不会为每个管道步骤(如过滤器或映射)创建中间集合

在您的情况下,您甚至没有功能操作管道,并且您不创建中间集合,因为您直接创建和填充结果。此外,您不能提前终止,因为无论如何您都想处理所有像素,所以Sequence 可能是合适的,但在这里不一定是性能改进。

如果您正在编译这个针对 JVM 的 Kotlin 代码,那么您至少可以做一件事来提高性能:

不要使用二维数组,而是使用带有特殊索引的一维数组。更具体地说,你可以写newImage[row * width + col],而不是newImage[row][col]。 这将避免双重内存引用和benefit from cache locality,因为您正在逐行迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-20
    • 2014-03-23
    • 2021-04-09
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多