根据切片Go中的键顺序对数据进行排序

时间:2020-02-25 08:34:34

标签: mysql sorting go slice

我使用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])
   }
}

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

谢谢。

1 个答案:

答案 0 :(得分:2)

使用MySQL的ORDER BY FIELD(id,'b','c','a')效率很高,如果您不介意扩展查询并在查询中加入逻辑,那么这没什么问题。

如果要在Go中执行此操作:Go的标准库提供了sort.Slice()函数来对任何切片进行排序。您必须向其传递一个less()函数,该函数必须告诉切片中的两个元素如何相互关联(如果一个元素小于另一个元素的话)。

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

为避免每次都必须线性搜索键片,您应该构建一个键图:

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

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

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

Go Playground上尝试一下。