如何有效地从Kotlin中的集合(前N个)中获取N个最低值?

如何有效地从Kotlin中的集合(前N个)中获取N个最低值?,kotlin,Kotlin,如何有效地从Kotlin中的集合(前N个)中获取N个最低值 除了{it.value}.take(n)之外,还有其他方法吗 假设我有一个包含+100500个元素的集合,我需要找到10个最低的元素。我担心由分类的将创建新的临时收集,以后只需要10件物品。您需要担心的更多 collectionOrSequence.sortedby{it.value}运行java.util.Arrays.sort,该操作将运行timSort(或mergeSort,如果请求) 很好,但通常以n*log(n)操作结束,这

如何有效地从Kotlin中的集合(前N个)中获取N个最低值

除了{it.value}.take(n)之外,还有其他方法吗


假设我有一个包含+100500个元素的集合,我需要找到10个最低的元素。我担心由分类的
将创建新的临时收集,以后只需要10件物品。

您需要担心的更多

  • collectionOrSequence.sortedby{it.value}
    运行
    java.util.Arrays.sort
    ,该操作将运行timSort(或mergeSort,如果请求)
  • 很好,但通常以n*log(n)操作结束,这远远超过复制数组的O(n)
  • 每个O(n*log.n)操作都将运行一个函数(您提供的lambda,
    {it.value}
    )-->,这将带来额外的有意义的开销
  • 最后,
    java.util.Array.sort
    将集合转换为数组并返回到列表-另外两种转换(您希望避免,但这是次要的)
有效的方法可能是:

  • 将要比较的值映射到一个列表中:O(n)个转换(每个元素一次),而不是O(n*log.n)或更多
  • 在创建的列表(或数组)上迭代,以在一次过程中收集N个最小的元素
    • 将迄今为止发现的N个最小元素及其索引保留在原始列表中。如果它很小(例如10项)-
      mutableList
      非常适合
    • 为小元素列表保留一个保持最大值的变量
    • 迭代原始集合时,将原始列表上的当前元素与小值列表的最大值进行比较。如果小于它-在“小列表”中替换它,并在其中找到更新的最大值
  • 使用“小列表”中的索引提取原始列表中的10个最小元素
  • 这将允许您从O(n*log.n)转到O(n)

    当然,如果时间很关键,那么最好对具体案例进行基准测试


    如果您在第一步设法提取原语以进行比较(例如,
    int
    long
    ),则效率会更高。

    您需要担心的问题更多

    • collectionOrSequence.sortedby{it.value}
      运行
      java.util.Arrays.sort
      ,该操作将运行timSort(或mergeSort,如果请求)
    • 很好,但通常以n*log(n)操作结束,这远远超过复制数组的O(n)
    • 每个O(n*log.n)操作都将运行一个函数(您提供的lambda,
      {it.value}
      )-->,这将带来额外的有意义的开销
    • 最后,
      java.util.Array.sort
      将集合转换为数组并返回到列表-另外两种转换(您希望避免,但这是次要的)
    有效的方法可能是:

  • 将要比较的值映射到一个列表中:O(n)个转换(每个元素一次),而不是O(n*log.n)或更多
  • 在创建的列表(或数组)上迭代,以在一次过程中收集N个最小的元素
    • 将迄今为止发现的N个最小元素及其索引保留在原始列表中。如果它很小(例如10项)-
      mutableList
      非常适合
    • 为小元素列表保留一个保持最大值的变量
    • 迭代原始集合时,将原始列表上的当前元素与小值列表的最大值进行比较。如果小于它-在“小列表”中替换它,并在其中找到更新的最大值
  • 使用“小列表”中的索引提取原始列表中的10个最小元素
  • 这将允许您从O(n*log.n)转到O(n)

    当然,如果时间很关键,那么最好对具体案例进行基准测试


    如果您在第一步设法提取原语作为比较的基础(例如
    int
    long
    ),则效率更高。

    您可以保留n个最小元素的列表,并根据需要进行更新,例如

    fun <T : Comparable<T>> top(n: Int, collection: Iterable<T>): List<T> {
        return collection.fold(ArrayList<T>()) { topList, candidate ->
            if (topList.size < n || candidate < topList.last()) {
                // ideally insert at the right place
                topList.add(candidate)
                topList.sort()
                // trim to size
                if (topList.size > n)
                    topList.removeAt(n)
            }
            topList
        }
    }
    
    fun top(n:Int,collection:Iterable):列表{
    return collection.fold(ArrayList()){topList,candidate->
    if(topList.sizen)
    topList.removeAt(n)
    }
    排行榜
    }
    }
    

    这样,您只需将列表中的当前元素与前n个元素中的最大元素进行一次比较,这通常比对整个列表进行排序要快

    您可以保留一个包含n个最小元素的列表,并根据需要进行更新,例如

    fun <T : Comparable<T>> top(n: Int, collection: Iterable<T>): List<T> {
        return collection.fold(ArrayList<T>()) { topList, candidate ->
            if (topList.size < n || candidate < topList.last()) {
                // ideally insert at the right place
                topList.add(candidate)
                topList.sort()
                // trim to size
                if (topList.size > n)
                    topList.removeAt(n)
            }
            topList
        }
    }
    
    fun top(n:Int,collection:Iterable):列表{
    return collection.fold(ArrayList()){topList,candidate->
    if(topList.sizen)
    topList.removeAt(n)
    }
    榜单
    }
    }
    

    这样,您只需将列表中的当前元素与前n个元素中的最大元素进行一次比较,这通常比对整个列表进行排序要快

    我建议根据典型的快速排序算法(按降序,并取前n个元素)实现您自己的排序方法,如果集合中有1k+值随机分布。如果集合中有1k+值随机分布,我建议基于典型的快速排序算法(按降序,并取前N个元素)实现您自己的排序方法。

    如果您在JVM上运行,您可以