搜索
首页后端开发Golang使用 Go 处理大型 CSV

想法是:

给定一个大型虚拟 CSV(100 万行)包含客户数据样本,并按照以下目标进行处理:

  • 从 CSV 中提取数据
  • 计算有多少数据/行
  • 对每个城市的客户数量进行分组
  • 按客户数量从高到低对城市进行排序
  • 计算处理时间

客户的 CSV 示例可以在此处下载 https://github.com/datablist/sample-csv-files

加载和提取数据

显然 Go 有用于 CSV 处理的标准库。我们不再需要第三方依赖来解决我们的问题,这很好。所以解决方案非常简单:

  // open the file to a reader interface
  c, err := os.Open("../data/customers-1000000.csv")
  if err != nil {
    log.Fatal(err)
  }
  defer c.Close()

  // load file reader into csv reader
  // Need to set FieldsPerRecord to -1 to skip fields checking
  r := csv.NewReader(c)
  r.FieldsPerRecord = -1
  r.ReuseRecord = true
  records, err := r.ReadAll()
  if err != nil {
    log.Fatal(err)
  }
  1. 从给定路径打开文件
  2. 将打开的文件加载到 csv 阅读器
  3. 将所有提取的 csv 记录/行值保存到记录切片中以供以后处理

FieldsPerRecord 设置为 -1,因为我想跳过对行的字段检查,因为每种格式的字段或列数可能不同

在此状态下,我们已经能够从 csv 加载和提取所有数据,并准备好进入下一个处理状态。我们还可以使用函数 len(records) 知道 CSV 中有多少行。

将总客户分组到每个城市

现在我们可以迭代记录并创建包含城市名称和总客户的地图,如下所示:

["Jakarta": 10, "Bandung": 200, ...]

csv 行中的城市数据位于第 7 个索引,代码如下所示

  // create hashmap to populate city with total customers based on the csv data rows
  // hashmap will looks like be ["city name": 100, ...]
  m := map[string]int{}
  for i, record := range records {
    // skip header row
    if i == 0 {
    continue
    }
    if _, found := m[record[6]]; found {
      m[record[6]]++
    } else {
      m[record[6]] = 1
    }
  }

如果城市地图不存在,则创建新地图并将客户总数设置为1。否则只需增加给定城市的总数。

现在我们的地图 m 包含城市的集合以及其中有多少客户。至此我们已经解决了每个城市有多少客户的分组问题。

对总客户数进行排序

我试图找到标准库中是否有任何函数可以对地图进行排序,但不幸的是我找不到它。排序仅适用于切片,因为我们可以根据索引位置重新排列数据顺序。所以,是的,让我们从当前的地图中切出一个切片。

// convert to slice first for sorting purposes
dc := []CityDistribution{}
for k, v := range m {
  dc = append(dc, CityDistribution{City: k, CustomerCount: v})
}

现在我们如何按 CustomerCount 从最高到最低排序?最常见的算法是使用气泡空头。虽然它不是最快的,但它可以完成这项工作。

冒泡排序是最简单的排序算法,如果相邻元素的顺序错误,它的工作原理是重复交换相邻元素。该算法不适合大型数据集,因为其平均和最坏情况时间复杂度相当高。

参考:https://www.geeksforgeeks.org/bubble-sort-algorithm/

使用我们的切片,它将循环数据并检查索引的下一个值,如果当前数据小于下一个索引,则交换它。详细算法可以在参考网站查看。

现在我们的排序过程可能是这样的

  // open the file to a reader interface
  c, err := os.Open("../data/customers-1000000.csv")
  if err != nil {
    log.Fatal(err)
  }
  defer c.Close()

  // load file reader into csv reader
  // Need to set FieldsPerRecord to -1 to skip fields checking
  r := csv.NewReader(c)
  r.FieldsPerRecord = -1
  r.ReuseRecord = true
  records, err := r.ReadAll()
  if err != nil {
    log.Fatal(err)
  }

循环结束时,最后的切片将为我们提供排序后的数据。

计算处理时间

计算处理时间非常简单,我们获取执行程序主进程之前和之后的时间戳并计算差值。在 Go 中,方法应该足够简单:

["Jakarta": 10, "Bandung": 200, ...]

结果

使用命令运行程序

  // create hashmap to populate city with total customers based on the csv data rows
  // hashmap will looks like be ["city name": 100, ...]
  m := map[string]int{}
  for i, record := range records {
    // skip header row
    if i == 0 {
    continue
    }
    if _, found := m[record[6]]; found {
      m[record[6]]++
    } else {
      m[record[6]] = 1
    }
  }

打印出来的是行数、排序数据和处理时间。像下面这样:

Large CSV Processing Using Go

正如 Go 性能所预期的那样,它在 1 秒内处理了 100 万行 csv!

所有已完成的代码已发布在我的 Github 存储库上:

https://github.com/didikz/csv-processing/tree/main/golang

经验教训

  • Go 中的 CSV 处理已经在标准库中可用,无需使用第 3 方库
  • 处理数据非常简单。面临的挑战是找出如何对数据进行排序,因为需要手动进行

想到什么?

我认为我当前的解决方案可能可以进一步优化,因为我循环提取了 csv 的所有记录来映射,如果我们检查 ReadAll() 源,它还有循环来根据给定的文件读取器创建切片。这样,1 百万行可以为 1 百万数据生成 2 个循环,这不太好。

我想如果我可以直接从文件读取器读取数据,它只需要 1 个循环,因为我可以直接从中创建地图。除了记录切片将在其他地方使用,但在本例中不使用。

我还没有时间弄清楚,但我也认为如果我手动完成会有一些缺点:

  • 可能需要处理更多解析过程中的错误
  • 我不确定它会减少多少处理时间来考虑解决方法是否值得

编码快乐!

以上是使用 Go 处理大型 CSV的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
学习GO String操纵:使用'字符串”软件包学习GO String操纵:使用'字符串”软件包May 09, 2025 am 12:07 AM

Go的"strings"包提供了丰富的功能,使字符串操作高效且简单。1)使用strings.Contains()检查子串。2)strings.Split()可用于解析数据,但需谨慎使用以避免性能问题。3)strings.Join()适用于格式化字符串,但对小数据集,循环使用 =更有效。4)对于大字符串,使用strings.Builder构建字符串更高效。

GO:使用标准'字符串”包的字符串操纵GO:使用标准'字符串”包的字符串操纵May 09, 2025 am 12:07 AM

Go语言使用"strings"包进行字符串操作。1)拼接字符串使用strings.Join函数。2)查找子串使用strings.Contains函数。3)替换字符串使用strings.Replace函数,这些函数高效且易用,适用于各种字符串处理任务。

使用GO的'字节”软件包掌握字节切片操作:实用指南使用GO的'字节”软件包掌握字节切片操作:实用指南May 09, 2025 am 12:02 AM

资助bytespackageingoisesential foreffited byteSemanipulation,uperingFunctionsLikeContains,index,andReplaceForsearchingangingAndModifyingBinaryData.itenHancesperformanceNandCoderAceAnibility,MakeitiTavitalToolToolToolToolToolToolToolToolToolForhandLingBinaryData,networkProtocols,networkProtocoLss,networkProtocols,andetFilei

学习GO二进制编码/解码:使用'编码/二进制”软件包学习GO二进制编码/解码:使用'编码/二进制”软件包May 08, 2025 am 12:13 AM

Go语言使用"encoding/binary"包进行二进制编码与解码。1)该包提供binary.Write和binary.Read函数,用于数据的写入和读取。2)需要注意选择正确的字节序(如BigEndian或LittleEndian)。3)数据对齐和错误处理也是关键,确保数据的正确性和性能。

GO:带有标准'字节”软件包的字节切​​片操作GO:带有标准'字节”软件包的字节切​​片操作May 08, 2025 am 12:09 AM

1)usebybytes.joinforconcatenatinges,2)bytes.bufferforincrementalWriter,3)bytes.indexorbytes.indexorbytes.indexbyteforsearching bytes.bytes.readereforrednerncretinging.isnchunk.ss.ind.inc.softes.4)

进行编码/二进制包:优化二进制操作的性能进行编码/二进制包:优化二进制操作的性能May 08, 2025 am 12:06 AM

theencoding/binarypackageingoiseforporptimizingBinaryBinaryOperationsDuetoitssupportforendiannessessandefficityDatahandling.toenhancePerformance:1)usebinary.nativeendiandiandiandiandiandiandiandian nessideendian toavoid avoidByteByteswapping.2)

Go Bytes软件包:简短的参考和提示Go Bytes软件包:简短的参考和提示May 08, 2025 am 12:05 AM

Go的bytes包主要用于高效处理字节切片。1)使用bytes.Buffer可以高效进行字符串拼接,避免不必要的内存分配。2)bytes.Equal函数用于快速比较字节切片。3)bytes.Index、bytes.Split和bytes.ReplaceAll函数可用于搜索和操作字节切片,但需注意性能问题。

Go Bytes软件包:字节切片操纵的实例Go Bytes软件包:字节切片操纵的实例May 08, 2025 am 12:01 AM

字节包提供了多种功能来高效处理字节切片。1)使用bytes.Contains检查字节序列。2)用bytes.Split分割字节切片。3)通过bytes.Replace替换字节序列。4)用bytes.Join连接多个字节切片。5)利用bytes.Buffer构建数据。6)结合bytes.Map进行错误处理和数据验证。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具