Golang中如何比较当前行数据与上一行数据?

Golang中如何比较当前行数据与上一行数据? 你好,

我该如何创建一个函数,该函数从文件中读取数据,并将当前行与上一行进行比较,以检查数据是否发生了变化?如果当前行的数据与上一行相同,则将该数据保存为 ID-1;但如果下一条记录与上一条记录不同,则保存一条新记录为 ID-2?

8 回复

我想写入第二个文件

更多关于Golang中如何比较当前行数据与上一行数据?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,这种情况也可能发生

你所说的“保存”是什么意思?你是想操作这个文件,还是想写入到另一个文件?

我只想累加这三行中的金额。例如,我有三个字段,如果记录号与上一条记录相同,那么我想累加这些数字并将一条记录写入文件。

记录号 金额A 金额B

好的。

另一个问题:如果连续三行内容相同,你希望如何处理?应该将多少行以及哪些行写入第二个文件?

同一个记录编号是否可能出现在多个不相邻的行中?这可能吗?

foo 123
bar 323
foo 456
bar 434
foo 987

对于这样的输入,将会有两个记录编号(foobar)。

那么你需要做类似以下的事情:

  • 创建一个以记录编号为键、以金额数组为值的 map
  • 遍历输入数据的每一行
    • 从行中提取记录编号和金额
    • 在 map 中查找该记录编号
      • 如果存在,则将金额追加到对应的金额数组中
      • 如果不存在,则创建一个新数组,将金额追加进去,并将该数组作为该记录编号的值存入 map
  • 遍历 map 的所有键(即记录编号)
    • 向输出写入一条包含该键及其对应金额数组的记录

在Go中实现逐行读取并比较当前行与上一行数据,可以通过以下方式实现:

package main

import (
	"bufio"
	"fmt"
	"os"
)

type Record struct {
	ID   int
	Data string
}

func processFile(filename string) ([]Record, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var records []Record
	scanner := bufio.NewScanner(file)
	
	var previousLine string
	currentID := 1
	lineNumber := 0

	for scanner.Scan() {
		currentLine := scanner.Text()
		lineNumber++

		if lineNumber == 1 {
			// 第一行直接保存
			records = append(records, Record{
				ID:   currentID,
				Data: currentLine,
			})
			previousLine = currentLine
			continue
		}

		if currentLine == previousLine {
			// 与上一行相同,使用相同ID
			records = append(records, Record{
				ID:   currentID,
				Data: currentLine,
			})
		} else {
			// 与上一行不同,使用新ID
			currentID++
			records = append(records, Record{
				ID:   currentID,
				Data: currentLine,
			})
			previousLine = currentLine
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return records, nil
}

func main() {
	// 示例:创建测试文件
	content := "apple\napple\nbanana\nbanana\nbanana\norange\napple"
	
	// 写入测试文件
	err := os.WriteFile("test.txt", []byte(content), 0644)
	if err != nil {
		fmt.Println("创建测试文件失败:", err)
		return
	}
	defer os.Remove("test.txt")

	// 处理文件
	records, err := processFile("test.txt")
	if err != nil {
		fmt.Println("处理文件失败:", err)
		return
	}

	// 输出结果
	fmt.Println("处理结果:")
	for _, record := range records {
		fmt.Printf("ID: %d, Data: %s\n", record.ID, record.Data)
	}
}

输出结果:

处理结果:
ID: 1, Data: apple
ID: 1, Data: apple
ID: 2, Data: banana
ID: 2, Data: banana
ID: 2, Data: banana
ID: 3, Data: orange
ID: 4, Data: apple

如果需要更高效的实现,可以使用以下优化版本:

func processFileOptimized(filename string) ([]Record, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	records := make([]Record, 0)
	scanner := bufio.NewScanner(file)
	
	var prevLine string
	currentID := 0
	isFirstLine := true

	for scanner.Scan() {
		line := scanner.Text()
		
		if isFirstLine {
			currentID = 1
			records = append(records, Record{ID: currentID, Data: line})
			prevLine = line
			isFirstLine = false
			continue
		}

		if line != prevLine {
			currentID++
			prevLine = line
		}
		
		records = append(records, Record{ID: currentID, Data: line})
	}

	return records, scanner.Err()
}

这个实现会逐行读取文件,比较当前行与上一行:

  • 如果当前行与上一行相同,使用相同的ID
  • 如果不同,ID递增并使用新ID
  • 第一行总是从ID=1开始
回到顶部