代码之家  ›  专栏  ›  技术社区  ›  juancsr

在go中循环切片/数组的有效方法

  •  1
  • juancsr  · 技术社区  · 7 年前

    基本上我有:

    package main
    
    import "fmt"
    
    type Struct1 struct {
        id   int
        name string
    }
    
    type Struct2 struct {
        id       int
        lastname string
    }
    
    type Struct3 struct {
        id   int
        real bool
    }
    
    func main() {
        var (
         s1 []Struct1
         s2 []Struct2
         s3 []Struct3
        )
        s1 = append(s1, Struct1{id: 1, name: "Eliot"}, Struct1{id: 2, name: "Tyrell"}, Struct1{id: 3, name: "Mr Robot"})
        s2 = append(s2, Struct2{id: 1, lastname: "Anderson"}, Struct2{id: 2, lastname: "Wellick"})
        s3 = append(s3, Struct3{id: 1, real: true}, Struct3{id: 2, real: true}, Struct3{id: 3, real: false})
    }
    

    我想展示这样的东西:

    • Eliot Anderson real(true)
    • Tyrell Wellick real(true)

    但我不想在s2内循环s1,然后在s3内循环s1

    例子:

    for i := 0; i < len(s1); i++ {
            for j := 0; j < len(s2); j++ {
                if s1[i].id == s2[j].id {
                    for k := 0; k < len(s3); k++ {
                        if s2[j].id == s3[k].id {
                            // some code ...
                        }
                    }
                }
            }
        }
    

    那么,还有什么其他方法可以做到这一点呢?

    3 回复  |  直到 7 年前
        1
  •  2
  •   Ravi R    7 年前

    正确的方法是将它们放入散列(在Golang中称为map)。这样,您就可以获得性能,并且只需在id上迭代一个循环。

    以下是示例数据:

    package main
    
    import (
        "fmt"
    )
    
    type Struct1 struct {
        id   int
        name string
    }
    
    type Struct2 struct {
        id       int
        lastname string
    }
    
    type Struct3 struct {
        id   int
        real bool
    }
    
    func main() {
        //var (
        //s1 []Struct1
        //      s2 []Struct2
        //  s3 []Struct3
        //  )
        s1Hash := make(map[int]Struct1)
        s2Hash := make(map[int]Struct2)
        s3Hash := make(map[int]Struct3)
    
        s11 := Struct1{id: 1, name: "Eliot"}
        s12 := Struct1{id: 2, name: "Tyrell"}
        s13 := Struct1{id: 3, name: "Mr Robot"}
        s1Hash[s11.id] = s11
        s1Hash[s12.id] = s12
        s1Hash[s13.id] = s13
    
        s21 := Struct2{id: 1, lastname: "Anderson"}
        s22 := Struct2{id: 2, lastname: "Wellick"}
        s2Hash[s21.id] = s21
        s2Hash[s22.id] = s22
    
        s31 := Struct3{id: 1, real: true}
        s32 := Struct3{id: 2, real: true}
        s33 := Struct3{id: 3, real: false}
        s3Hash[s31.id] = s31
        s3Hash[s32.id] = s32
        s3Hash[s33.id] = s33
    
        //s1 = append(s1, Struct1{id: 1, name: "Eliot"}, Struct1{id: 2, name: "Tyrell"}, Struct1{id: 3, name: "Mr Robot"})
        //s2 = append(s2, Struct2{id: 1, lastname: "Anderson"}, Struct2{id: 2, lastname: "Wellick"})
        //s3 = append(s3, Struct3{id: 1, real: true}, Struct3{id: 2, real: true}, Struct3{id: 3, real: false})
    
        //i to loop over possible id range
        for i := 1; i <= len(s1Hash); i++ {
            fmt.Println("i is ", i)
            if _, ok := s1Hash[i]; ok {
                fmt.Printf("Name: %s ", s1Hash[i].name)
            }
    
            if _, ok := s2Hash[i]; ok {
                fmt.Printf(" Lastname: %s ", s2Hash[i].lastname)
            }
    
            if _, ok := s3Hash[i]; ok {
                fmt.Printf(" Real: %t\n", s3Hash[i].real)
            }
            //fmt.Printf("%s %s real:%t\n", s1Hash[i].name, s2[i].lastname, s3[i].real)
        }
    
    }
    

    输出:

    i is  1
    Name: Eliot  Lastname: Anderson  Real: true
    i is  2
    Name: Tyrell  Lastname: Wellick  Real: true
    i is  3
    Name: Mr Robot  Real: false
    

    检查 this 在操场上。希望这有帮助!

    p、 最后,如果您可以删除某些ID的所有结构条目并添加新的ID,您可以考虑将有效ID添加到映射中 map[int]bool ( mymap[id] = true )并使用 range 而不是 for i.. 同上。

        2
  •  0
  •   Daniel Tran    7 年前

    使用地图按人名索引数据。

    type Person struct {
         firstName: string
         lastName: string 
         real: string
    }
    
    var data map[int]Person
    

    然后查找并将数据放到地图上。

        3
  •  0
  •   Eugene Lisitsky    7 年前

    事实上,要连接所有第一个元素,然后连接所有第二个元素等等,你不需要在一个循环中做一个循环:

    将每个切片准备为地图:

    m1 := make(map[int]string)
    for i:=0; i < len(s1); i ++ {
        m1[s1[i].id] = s1[i].Name
    }
    

    其他两片也一样。 最后迭代一次:

    for i:=0; i < len(s1); i ++ {
        fmt.Println(m1[i], m2[i], m3[i])
    }
    

    该解决方案假设所有切片都有相应的项。如果没有,您应该决定如何处理没有片段的元素:忽略、用一些占位符替换空白、中断整个循环等 firstName 是强制性的(我们将对此进行迭代), secondName 是可选的,应替换为 ? 如果不存在,则整个循环中绝对必须使用实数-如果不存在实数,则中断进一步的工作并返回空切片:

    type Person struct { // corrected struct from the neighbour recipe
         firstName: string
         lastName: string 
         real: bool
    }
    
    var persons []Person // slice for result
    
    for i, firstName := range m1 { // iterate by keys and values of m1
        secondName, ok := m2[i]
        if !ok {
           secondName = "?"
        }
        real, ok := m3[i]
        if !ok {
           persons = []Person
           break
        }
        person := Person{firstName, secondName, real}
        persons = append(persons, person)
    }