【问题标题】:Sort data according to sequence of keys in a slice Go根据切片中的键序列对数据进行排序 Go
【发布时间】:2020-06-08 22:32:55
【问题描述】:

我使用 Go 和 MySQL 数据库。假设我有一段这样的字符串:[]string{"b", "c", "a"},我希望得到这样的最终数据:

[]Student{
    Student{ID: "b", Name: "Ben"},
    Student{ID: "c", Name: "Carl"},
    Student{ID: "a", Name: "Alexander"},
}

当我想构建 MySQL 查询时,使用ORDER BY FIELD(id,'b','c','a') 是一种有效的方式吗?或者如果我不使用它,我会有这样的代码:

keys := []string{"b", "c", "a"}

...

students := make([]Student, 0)
for rows.Next() {
    s := Student{}
    err := rows.Scan(&s.ID, &s.Name)
    if err != nil {
        log.Fatal(err)
    }
    students = append(students, s)
}

mStudents := make(map[string]Student, 0)
for _, v := range students {
    mStudents[v.ID] = v
}

finalData := make([]Student, 0)
for _, v := range keys {
   if _, ok := mStudents[v]; ok {
       finalData = append(finalData, mStudents[v])
   }
}

但我认为这是一种非常低效的方式。那么,还有其他方法吗?

谢谢。

【问题讨论】:

    标签: mysql sorting go slice


    【解决方案1】:

    使用 MySQL 的 ORDER BY FIELD(id,'b','c','a') 是高效的,如果您不介意扩展查询并在查询中包含您的逻辑,那么它没有任何问题。

    如果你想在 Go 中这样做:Go 的标准库提供了一个 sort.Slice() 函数来对任何切片进行排序。您必须将 less() 函数传递给它,该函数必须告诉切片中的 2 个元素如何相互关联,如果一个小于另一个。

    你想要一个由另一个指定的顺序,排序 keys 切片。因此,基本上要判断一个学生是否比另一个学生“少”,您需要比较他们的键的索引。

    为避免每次都对键切片进行线性搜索,您应该构建它们的映射:

    m := map[string]int{}
    for i, k := range keys {
        m[k] = i
    }
    

    因此,作为“less”逻辑基础的索引是一个简单的地图查找:

    sort.Slice(students, func(i, j int) bool {
        return m[students[i].ID] < m[students[j].ID]
    })
    

    Go Playground 上试试这个。

    【讨论】:

    • 那么,哪一个可能更有效?直接在 MySQL 中订购或使用sort.Slice()?
    • @RiefSapthana 使用查询进行排序很可能会更快。 Go 中的排序为您提供了更多的控制权和灵活性。使用任何你喜欢的。
    • 使用最好的工具来完成手头的任务。您已经在使用 SQL,因此请利用它的功能,它会简化您的客户端代码。
    猜你喜欢
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 2016-12-01
    • 2013-05-14
    相关资源
    最近更新 更多