为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 Golang 在结构切片中找到最频繁的整数

如何使用 Golang 在结构切片中找到最频繁的整数

Go
慕妹3242003 2023-02-21 13:21:33
这是问题的总结:我试图从来自解码的 .json 文件(包含字符串“name”和整数“age”)的结构中找到最常见的“age”。之后我需要根据“年龄”的最大出现频率打印“姓名”。根据“年龄”的最大出现次数打印的“姓名”需要按字母顺序排序输入(.json):[{"name": "John","age": 15},{"name": "Peter","age": 12},{"name": "Roger","age": 12},{"name": "Anne","age": 44},{"name": "Marry","age": 15},{"name": "Nancy","age": 15}]输出:['John', 'Mary', 'Nancy']。解释:因为数据中出现次数最多的年龄是 15 岁(出现 3 次),所以输出应该是一个包含三个人姓名的字符串数组,在这种情况下应该是 ['John', 'Mary', 'Nancy' ].例外 :如果有多个“年龄”具有相同的最大出现次数,我需要拆分数据并将它们打印到不同的数组中(即当“Anne”年龄为 12 岁时,结果为:['John', 'Mary ', '南希'], ['安妮', '彼得', '罗杰']这是我尝试过的(在 Golang 中):package main{import (    "encoding/json"    "fmt"    "os"    "sort")// 1. preparing the empty struct for .jsontype Passanger struct {    Name string `json:"name"`    Age  int    `json:"age"`}func main() {    // 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 passangers []Passanger    err2 := json.Unmarshal(content, &passangers)    if err2 != nil {        fmt.Println("Error JSON Unmarshalling")        fmt.Println(err2.Error())    }    // 4. find most frequent age numbers (?)    for _, v := range passangers {        // this code only show the Age on every line        fmt.Println(v.Age)    }    // 5. print the name and sort them apabethically (?)       // use sort.slice package       // implement group based by "max-occurence-age"}从昨天开始就卡住了,我还尝试从许多编码挑战问题中实施解决方案,例如:func majorityElement(arr int) int {    sort.Ints(arr)    return arr[len(arr)/2]}但我仍在努力理解如何将 Passanger 切片中的“年龄”值作为整数输入 (arr int) 处理到上面的代码中。我在网上找到的其他解决方案是通过迭代 map[int]int 来找到最大频率:func main(){    arr := []int{90, 70, 30, 30, 10, 80, 40, 50, 40, 30}    freq := make(map[int]int)    for _ , num :=  range arr {        freq[num] = freq[num]+1    }    fmt.Println("Frequency of the Array is : ", freq)}但话又说回来,.json 文件不仅包含整数(年龄),还包含字符串(名称)格式,我仍然不知道如何分别处理“名称”和“年龄”..我真的需要一个适当的指导。*** 这是我上面提到的源代码 (main.go) 和 (.json) 文件: https: //github.com/ariejanuarb/golang-json
查看完整描述

2 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

在实施解决方案之前要做什么

在我大学的第一年,我的老师总是对我和我的同学们重复一些事情,不要先写代码,特别是如果你是初学者,请按照以下步骤操作:

  • 写下你想要发生的事

  • 将问题详细化为小步骤

  • 写出分支时的所有场景和案例

  • 写入输入和输出(方法/函数签名)

  • 检查它们是否适合彼此

让我们按照这些步骤...

写下你想要发生的事

你已经很好地定义了你的问题,所以我将跳过这一步。

让我们进一步详细说明

  1. 你有一份乘客名单

  2. 你想按年龄对乘客进行分组

  3. 你想看看哪些是最常见的/哪些乘客最多。

  4. 你想按字母顺序打印名字

分支出

  • 场景一:一个组的规模比其他所有组都大。

  • 情况二:两个或多个组具有相同的大小并且比其他组大。

可能会有更多的场景,但它们是你的

输入输出 ??

现在我们已经知道我们必须做什么,我们将检查每个步骤的输入和输出以实现这个目标。

步骤:

  1. 你有一份乘客名单

  • 输入 => 无或文件名(字符串)

  • 输出=> []乘客

  1. 你想按年龄对乘客进行分组

  • input => []Passenger // 乘客列表

  • output => map[int][]int 或 map[int][]&Passenger // ageGroups

第一种,括号内的是全组年龄。

第二种类型是一个列表,其中包含:

  • 乘客在列表中的位置

  • 物体/乘客在内存中的地址

这并不重要,只要我们可以轻松地从列表中取回乘客而无需再次迭代即可。

  1. 你想看看哪些是最常见的/哪些乘客最多。

  • 输入 => 组(年龄组)

所以这里我们有场景 1 和场景 2 的分支......这意味着它必须对所有场景都有效或使用条件将它们分支出来。

  • 场景 1 的输出 => 最常见的年龄 (int)

  • 场景 2 的输出 => 最常见的年龄 ([]int)

我们可以看到场景 1 的输出可以与场景 2 的输出合并

  1. 您想要按年龄组中所有乘客的字母顺序打印姓名

    老实说,如果你愿意,你可以跳过这个。

    • 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("}")

    }

}


查看完整回答
反对 回复 2023-02-21
?
冉冉说

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

}


查看完整回答
反对 回复 2023-02-21
  • 2 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号