You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言:优化Map创建阶段的元素出现次数统计实现

需求说明

逐词读取给定文本数据,提取宽度、高度、厚度信息,统计每组参数的出现次数,最终生成包含Quantity字段的Measurement列表用于数据库插入。现有代码可实现该功能,但写法繁琐冗余,希望获得更简洁优雅的实现方案,尤其是在对象创建耗时的场景下高效统计唯一元素出现次数。

输入数据

1190 W X 1648 H X 14 T
S
1190 W X 1254 H X 14 T
S
1190 W X 1254 H X 14 T
S
1190 W X 1254 H X 14 T
S
1190 W X 1254 H X 14 T
S
1190 W X 1648 H X 14 T

现有实现代码

func CreateGlassBoxNew(db *gorm.DB, boxID uint, internalName string, glassBoxData []byte) {
    m := make(map[string]Measurement)
    var outerList []string
    var innerList []int
    var index = 0
    var count = 0
    var appendStr string
    scanner := bufio.NewScanner(strings.NewReader(string(glassBoxData)))
    scanner.Split(bufio.ScanWords)
    for scanner.Scan() {
        if scanner.Text() == "S" || scanner.Text() == "W" || scanner.Text() == "H" || scanner.Text() == "T" || scanner.Text() == "X" {
            continue
        }

        appendStr += scanner.Text() + "-"
        innerList = append(innerList, addMeasurementInt(scanner.Text()))

        index++
        if index == 3 {
            dump.P(innerList)
            count++
            fmt.Println(count)
            m[appendStr] = Measurement{
                Width:      innerList[0],
                Height:     innerList[1],
                Thicknes:   innerList[2],
                Quantity:   count,
                GlassBoxID: boxID,
            }
            innerList = nil
            outerList = append(outerList, appendStr)

            appendStr = ""
            index = 0

        }
    }
    if err := scanner.Err(); err != nil {
        dump.P(err)
    }

    dump.P(m)

    occurenceMap := CountOccurence(outerList)

    var finalList []Measurement
    for key, element := range m {
        finalList = append(finalList, Measurement{
            Width:      element.Width,
            Height:     element.Height,
            Thicknes:   element.Thicknes,
            Quantity:   occurenceMap[key],
            GlassBoxID: boxID,
        })
    }
    dump.P(finalList)
}

预期插入结果

[]models.Measurement [ #len=2
  models.Measurement {
    Width: int(1190),
    Height: int(1648),
    Thicknes: int(14),
    Quantity: int(2),
    GlassBoxID: uint(3436),
    BluePrintName: *string<nil>,
  },
  models.Measurement {
    Width: int(1190),
    Height: int(1254),
    Thicknes: int(14),
    Quantity: int(4),
    GlassBoxID: uint(3436),
    BluePrintName: *string<nil>,
  },
],

优化后的实现方案

import (
    "bufio"
    "strconv"
    "strings"
)

func CreateGlassBoxNew(db *gorm.DB, boxID uint, internalName string, glassBoxData []byte) {
    // 用仅包含核心参数的Measurement作为map key,直接统计出现次数
    countMap := make(map[Measurement]int)
    scanner := bufio.NewScanner(strings.NewReader(string(glassBoxData)))
    scanner.Split(bufio.ScanWords)

    var currentMeas Measurement
    paramIdx := 0

    for scanner.Scan() {
        word := scanner.Text()
        // 跳过无关标记字符
        if word == "S" || word == "W" || word == "H" || word == "T" || word == "X" {
            continue
        }

        val, err := strconv.Atoi(word)
        if err != nil {
            dump.P(err)
            continue
        }

        // 按顺序赋值宽、高、厚
        switch paramIdx {
        case 0:
            currentMeas.Width = val
        case 1:
            currentMeas.Height = val
        case 2:
            currentMeas.Thicknes = val
            // 三个参数收集完成,更新计数
            countMap[currentMeas]++
            // 重置状态
            paramIdx = -1
            currentMeas = Measurement{}
        }
        paramIdx++
    }

    if err := scanner.Err(); err != nil {
        dump.P(err)
    }

    // 转换为最终的插入列表
    var finalList []Measurement
    for coreMeas, quantity := range countMap {
        finalList = append(finalList, Measurement{
            Width:        coreMeas.Width,
            Height:       coreMeas.Height,
            Thicknes:     coreMeas.Thicknes,
            Quantity:     quantity,
            GlassBoxID:   boxID,
        })
    }

    dump.P(finalList)
    // 执行数据库插入:db.Create(&finalList)
}

// Measurement结构体需保证核心字段为可比较类型(int/uint默认支持)
type Measurement struct {
    Width         int
    Height        int
    Thicknes      int
    Quantity      int
    GlassBoxID    uint
    BluePrintName *string
}

优化说明

  • 减少冗余操作:直接用包含宽/高/厚的Measurement作为map key,省去原代码中生成字符串key、维护统计列表的步骤,一次遍历完成数据收集与计数。
  • 提升性能:避免重复创建Measurement对象,仅在生成最终插入列表时创建完整对象,适合对象初始化耗时的场景。
  • 逻辑简化:去掉多个临时变量,流程更清晰,降低维护成本。

内容的提问来源于stack exchange,提问作者JonB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:35:27