Golang中如何缩减切片长度

Golang中如何缩减切片长度 你好,

我正在尝试使用一个最大数量参数来减少切片的长度。以下是代码。它看起来还不错,但我愿意听取建议 🙂

package main

import "fmt"

func main() {
	records := selectRecords(1000)
	fmt.Println(len(records))
}

func selectRecords(maximumRecordCount float64) []string {
	records := make([]string, 5987)
	recordCount := float64(len(records))
	if recordCount <= maximumRecordCount {
		return records
	}
	step := recordCount / maximumRecordCount
	var filteredRecords []string
	for i := 0.0; i < recordCount; i += step {
		filteredRecords = append(filteredRecords, records[int(i)])
	}
	return filteredRecords
}

更多关于Golang中如何缩减切片长度的实战教程也可以访问 https://www.itying.com/category-94-b0.html

11 回复

为什么不一开始就这样做呢?

records := make([]string, int(maximumRecordCount))

更多关于Golang中如何缩减切片长度的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个示例。我正在从数据库中根据日期范围选择实际的记录。

a:=make([]string,0,1000)

我正在使用它们来编写一个服务器监控工具,以进行学习。它们的数值变化较小,间隔为15秒。

决定省略哪些记录的标准是什么?返回 [a, c, e] 比返回 [a, b, c] 好在哪?

我使用日期范围来选择记录(每条记录包含一个值和一个时间戳)。因此,显示记录时,以相等的步长省略额外的记录,这样感觉更正确,对吗?

在不了解具体场景的情况下很难回答。如果查询是为了获取当月收入最高的N天或者每日完成的平均订单数,那么删除行并不是正确的计算方法。你应该将数据聚合到一个更小的数据集中。能否提供更多关于你将如何使用这个 selectRecords 函数的信息?

func main() {
    fmt.Println("hello world")
}

你好,

由于该切片是系统在配置的时间间隔内记录的利用率数据,我决定使用一个随机生成的索引切片来减少切片的长度(记录数量)。这个索引切片具有指定的长度以及起始和结束位置。每次刷新前端时,它都会生成随机的图表 😊 这是相关代码。我对结果很满意。感谢你的建议。

响应时间大约减少了 30%。

func main() {
    fmt.Println("hello world")
}

感谢这个想法。抱歉补充得有点晚,我将从后端发送数据并在前端的图表上打印这些记录。记录的移除必须是均衡的。 例如,我收到了 [a, b, c, d, e] 这5条记录。我想将其长度缩减为 [a, c, e] 这3条记录。

最大可见点数看起来像是1000,而我收到了大约150000条记录 :slight_smile:

我认为你要找的是:

func selectRecords(maximumRecordCount int) []string {
	records := make([]string, 5987)
	if len(records) > maximumRecordCount {
		return records[:maximumRecordCount]
	}
	return records
}

请注意,这仍然会使用与原始 records 切片相同的内存,但遍历结果将限制在 maximumRecordCount 范围内。如果你确实想要释放较大的切片,必须将数据复制到一个较小的切片中:

func selectRecords(maximumRecordCount int) []string {
	records := make([]string, 5987)
	if len(records) <= maximumRecordCount {
		return records
	}
	limited := make([]string, maximumRecordCount)
	copy(limited, records)
	return limited
}

我建议不要使用 float64 来跟踪长度。如果有人传入 1.3 会怎样?长度应该向下取整为 1 还是向上取整为 2?只需传递一个 int 参数,将这个问题留给调用者处理,这样你的函数就只需要关注一件事。

这是一个常见的需求,但当前实现有几个问题:

  1. 类型不匹配maximumRecordCountfloat64,但切片长度应该是整数
  2. 精度问题:浮点数循环可能导致索引越界
  3. 效率问题:使用浮点数步长计算不够精确

以下是更简洁的实现:

package main

import "fmt"

func main() {
	records := selectRecords(1000)
	fmt.Println(len(records)) // 输出: 1000
}

func selectRecords(maximumRecordCount int) []string {
	records := make([]string, 5987)
	
	if len(records) <= maximumRecordCount {
		return records
	}
	
	// 直接使用切片操作缩减长度
	return records[:maximumRecordCount]
}

如果需要进行等间隔采样(而不是简单截断),可以这样实现:

func selectRecordsSampled(maximumRecordCount int) []string {
	records := make([]string, 5987)
	
	if len(records) <= maximumRecordCount {
		return records
	}
	
	step := len(records) / maximumRecordCount
	filteredRecords := make([]string, 0, maximumRecordCount)
	
	for i := 0; i < len(records) && len(filteredRecords) < maximumRecordCount; i += step {
		filteredRecords = append(filteredRecords, records[i])
	}
	
	// 确保返回的切片长度不超过最大值
	if len(filteredRecords) > maximumRecordCount {
		return filteredRecords[:maximumRecordCount]
	}
	
	return filteredRecords
}

对于简单的长度缩减,直接使用切片操作 records[:maximumRecordCount] 是最佳选择,它时间复杂度 O(1) 且不会分配新内存(底层数组共享)。

回到顶部