2 回答

TA贡献1155条经验 获得超0个赞
在实施解决方案之前要做什么
在我大学的第一年,我的老师总是对我和我的同学们重复一些事情,不要先写代码,特别是如果你是初学者,请按照以下步骤操作:
写下你想要发生的事
将问题详细化为小步骤
写出分支时的所有场景和案例
写入输入和输出(方法/函数签名)
检查它们是否适合彼此
让我们按照这些步骤...
写下你想要发生的事
你已经很好地定义了你的问题,所以我将跳过这一步。
让我们进一步详细说明
你有一份乘客名单
你想按年龄对乘客进行分组
你想看看哪些是最常见的/哪些乘客最多。
你想按字母顺序打印名字
分支出
场景一:一个组的规模比其他所有组都大。
情况二:两个或多个组具有相同的大小并且比其他组大。
可能会有更多的场景,但它们是你的
输入输出 ??
现在我们已经知道我们必须做什么,我们将检查每个步骤的输入和输出以实现这个目标。
步骤:
你有一份乘客名单
输入 => 无或文件名(字符串)
输出=> []乘客
你想按年龄对乘客进行分组
input => []Passenger // 乘客列表
output => map[int][]int 或 map[int][]&Passenger // ageGroups
第一种,括号内的是全组年龄。
第二种类型是一个列表,其中包含:
乘客在列表中的位置
物体/乘客在内存中的地址
这并不重要,只要我们可以轻松地从列表中取回乘客而无需再次迭代即可。
你想看看哪些是最常见的/哪些乘客最多。
输入 => 组(年龄组)
所以这里我们有场景 1 和场景 2 的分支......这意味着它必须对所有场景都有效或使用条件将它们分支出来。
场景 1 的输出 => 最常见的年龄 (int)
场景 2 的输出 => 最常见的年龄 ([]int)
我们可以看到场景 1 的输出可以与场景 2 的输出合并
您想要按年龄组中所有乘客的字母顺序打印姓名
老实说,如果你愿意,你可以跳过这个。
input => groups ([]Passenger) + ages ([]int) + passenger list ([]Passenger).
output => string or []byte or nothing if you just print it...
检查后,是时候编码了
让我们首先创建适合我们签名的功能
type Passenger struct {
Name string `json:"name"`
Age int `json:"age"`
}
func GetPassengerList() []Passenger{
// 2. load the json file
content, err := os.ReadFile("passanger.json")
if err != nil {
fmt.Println(err.Error())
}
// 3. parse json file to slice
var passengers []Passenger
err2 := json.Unmarshal(content, &passengers)
if err2 != nil {
fmt.Println("Error JSON Unmarshalling")
fmt.Println(err2.Error())
}
return passengers
}
// 4a. Group by Age
func GroupByAge(passengers []Passenger) map[int][]int {
group := make(map[int][]int, 0)
for index, passenger := range passengers {
ageGroup := group[passenger.Age]
ageGroup = append(ageGroup, index)
group[passenger.Age] = ageGroup
}
return group
}
// 4b. find the most frequent age numbers
func FindMostCommonAge(ageGroups map[int][]int) []int {
mostFrequentAges := make([]int, 0)
biggestGroupSize := 0
// find most frequent age numbers
for age, ageGroup := range ageGroups {
// is most frequent age
if biggestGroupSize < len(ageGroup) {
biggestGroupSize = len(ageGroup)
mostFrequentAges = []int{age}
} else if biggestGroupSize == len(ageGroup) { // is one of the most frequent age
mostFrequentAges = append(mostFrequentAges, age)
}
// is not one of the most frequent age so does nothing
}
return mostFrequentAges
}
func main() {
passengers := loadPassengers()
// I am lazy but if you want you could sort the
// smaller slice before printing to increase performance
sort.Slice(passengers, func(i, j int) bool {
if passengers[i].Age == passengers[j].Age {
return passengers[i].Name < passengers[j].Name
}
return passengers[i].Age < passengers[j].Age
})
// age => []position
// Length of the array count as the number of occurences
ageGrouper := GroupByAge(passengers)
mostFrequentAges := FindMostCommonAge(ageGrouper)
// print the passenger
for _, age := range mostFrequentAges {
fmt.Println("{")
for _, passengerIndex := range ageGrouper[age] {
fmt.Println("\t", passengers[passengerIndex].Name)
}
fmt.Println("}")
}
}

TA贡献1877条经验 获得超1个赞
应该比任何更复杂
按年龄和名称对源切片进行排序
将其分解成具有共同年龄的序列,并且
在进行过程中,跟踪最常见的
是这样的:
https://goplay.tools/snippet/6pCpkTEaDXN
type Person struct {
Age int
Name string
}
func MostCommonAge(persons []Person) (mostCommonAge int, names []string) {
sorted := make([]Person, len(persons))
copy(sorted, persons)
// sort the slice by age and then by name
sort.Slice(sorted, func(x, y int) bool {
left, right := sorted[x], sorted[y]
switch {
case left.Age < right.Age:
return true
case left.Age > right.Age:
return false
default:
return left.Name < right.Name
}
})
updateMostCommonAge := func(seq []Person) (int, []string) {
if len(seq) > len(names) {
buf := make([]string, len(seq))
for i := 0; i < len(seq); i++ {
buf[i] = seq[i].Name
}
mostCommonAge = seq[0].Age
names = buf
}
return mostCommonAge, names
}
for lo, hi := 0, 0; lo < len(sorted); lo = hi {
for hi = lo; hi < len(sorted) && sorted[lo].Age == sorted[hi].Age; {
hi++
}
mostCommonAge, names = updateMostCommonAge(sorted[lo:hi])
}
return mostCommonAge, names
}
另一种方法使用更多内存,但更简单一些。在这里,我们按年龄构建了一个名字映射,然后对其进行迭代以找到具有最长名字列表的键。
https://goplay.tools/snippet/_zmMys516IM
type Person struct {
Age int
Name string
}
func MostCommonAge(persons []Person) (mostCommonAge int, names []string) {
namesByAge := map[int][]string{}
for _, p := range persons {
value, found := namesByAge[p.Age]
if !found {
value = []string{}
}
namesByAge[p.Age] = append(value, p.Name)
}
for age, nameList := range namesByAge {
if len(nameList) > len(names) {
mostCommonAge, names = age, nameList
}
}
return mostCommonAge, names
}
- 2 回答
- 0 关注
- 115 浏览
添加回答
举报