Golang中如何搜索结构体数组中的数据

Golang中如何搜索结构体数组中的数据 我想在结构体数组中搜索数据。 Var vcustomer :=[]customers 示例:select * from customers 存储在 vcustomer 中

Var vorder := []orders Select * from orders 存储在 borders 中

For _,cust range vcustomers{
Find orders,}

如何从订单数组中查找客户的订单。

一种方法我们可以进行比较。

是否有其他更快捷的方法,例如建立索引和搜索。

11 回复

请给我示例

更多关于Golang中如何搜索结构体数组中的数据的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果你能提供一些具体的代码,我可以为你添加几行。

非常感谢,它的速度真的很快,逻辑也很完美。

映射持有指向每个结构体的指针,因此只需极少额外内存且无需复制。在时空权衡方面,只需少量额外空间即可节省大量时间。

如果你需要多次搜索,可以创建一个快速的数据结构,例如 map[customer][]order。如果你只需要搜索一次,那么线性遍历订单切片即可。

map[customer][]order

在你的方法中,我必须将我的结构体数据转换为映射。

根据你的建议,使用以下代码:

studentsByCode := make(map[int]*Students)
for i := range _students {
    studentsByCode[s[i].Student_code] = &s[i]
}

packs: 我想要 JSON 格式的数据

你可以在结构体的标签中添加 json:"...",但可能甚至不需要这样做。然后执行 json.Marshal(_students)

packs: 我想通过使用 student_code 来关联这两份数据

这正是构建 studentsByCode 映射的代码所做的。还缺少什么吗?

我的需求是 我希望JSON格式如下:

{
    Student_code : 1
    Batch_division : "A"
    Rollno : 10
    Name : "Mr james"
    marks : [ {"Student_code : 1 , Subjectname : "maths",Marks : 60},
    {"Student_code : 1 , Subjectname : "eng",Marks : 70}]
}

我正在执行两个独立的查询。我希望通过使用student_code来关联这两组数据。

如果你创建一个从学生代码到 Students 的映射,那么你就不需要执行 O(n^2) 的嵌套循环。以下是 O(n) 的复杂度。我不明白为什么你在内层循环中创建一个新的 SudentsMarks,而不是复用切片中的那个。

studentsByCode := make(map[int]*Students)
for i := range _students {
  studentsByCode[s[i].Student_code] = &s[i]
}

for _, m := range _studentsMarks {
  s,ok := studentsByCode[m.student_code]
	if ok {
		s.Marks = append(s.Marks, m)
	} else {
		panic("missing student for marks")
	}
}
type SudentsMarks struct {
	Student_code int `db:"student_code"`
	Subjectname string `db:"subjectname"`
	Marks   int    `db:"marks"`
}
type Students struct {
	Student_code int `db:"student_code"`
	Batch_division     string `db:"batch_division" `
	Rollno             int    `db:"rollno" `
	Name           string `db:"fullname" `
	Marks              []SudentsMarks
}
var err error	
var _students = []Students{}	
var _studentsMarks = []SudentsMarks{}
studentquery := `select * from students`
marksquery := `select * from marks`
err = Mydb.Select(&studentquery, studentquery)
if err != nil {
	return err
}
err = Mydb.Select(&_studentsMarks, marksquery)
if err != nil {
	return err
}

现在,我们想要将成绩嵌入到学生信息中,因为在我的学生结构体中,成绩是一个数组。 我们正在使用线性搜索。

for nstudentloop, student := range _students {

		for _, marksloop := range _studentsMarks {
			if marksloop.student_code == student.student_code {

				_marks := SudentsMarks{}
				_marks.Marks = marksloop.Marks
				_marks.student_code = marksloop.student_code
				_marks.subjectname = marksloop.subjectname

				_students[nstudentloop].Marks = append(_students[nstudentloop].Marks, _marks)
				
			} else {
				break
			}
		}
		

	}

这段代码可以工作,但在我看来,可能有更好的方法来解决这个问题。 成绩循环会运行多次。

在Golang中搜索结构体数组数据时,可以通过建立索引来提高搜索效率。以下是几种实现方式:

1. 使用Map建立索引(推荐)

// 建立订单索引:customerID -> []Order
func createOrderIndex(orders []Order) map[int][]Order {
    index := make(map[int][]Order)
    for _, order := range orders {
        index[order.CustomerID] = append(index[order.CustomerID], order)
    }
    return index
}

// 使用索引查找
func findOrdersByCustomer(customers []Customer, orders []Order) {
    // 建立订单索引
    orderIndex := createOrderIndex(orders)
    
    for _, cust := range customers {
        // 直接通过索引获取订单,时间复杂度O(1)
        customerOrders := orderIndex[cust.ID]
        if len(customerOrders) > 0 {
            fmt.Printf("Customer %d has %d orders\n", cust.ID, len(customerOrders))
        }
    }
}

2. 使用复合索引(多字段搜索)

type Order struct {
    ID         int
    CustomerID int
    ProductID  int
    Amount     float64
}

// 建立复合索引
func createMultiIndex(orders []Order) map[string][]Order {
    index := make(map[string][]Order)
    for _, order := range orders {
        // 创建复合键
        key := fmt.Sprintf("%d_%d", order.CustomerID, order.ProductID)
        index[key] = append(index[key], order)
    }
    return index
}

// 查找特定客户和产品的订单
func findSpecificOrders(customerID, productID int, index map[string][]Order) []Order {
    key := fmt.Sprintf("%d_%d", customerID, productID)
    return index[key]
}

3. 使用排序和二分查找

import "sort"

// 按CustomerID排序订单
func sortOrdersByCustomerID(orders []Order) {
    sort.Slice(orders, func(i, j int) bool {
        return orders[i].CustomerID < orders[j].CustomerID
    })
}

// 二分查找特定客户的所有订单
func findOrdersBinarySearch(customerID int, orders []Order) []Order {
    // 首先找到第一个匹配的订单
    start := sort.Search(len(orders), func(i int) bool {
        return orders[i].CustomerID >= customerID
    })
    
    if start >= len(orders) || orders[start].CustomerID != customerID {
        return nil
    }
    
    // 找到最后一个匹配的订单
    end := start
    for end < len(orders) && orders[end].CustomerID == customerID {
        end++
    }
    
    return orders[start:end]
}

4. 完整示例代码

package main

import (
    "fmt"
    "sort"
)

type Customer struct {
    ID   int
    Name string
}

type Order struct {
    ID         int
    CustomerID int
    Product    string
    Amount     float64
}

func main() {
    // 示例数据
    customers := []Customer{
        {ID: 1, Name: "Alice"},
        {ID: 2, Name: "Bob"},
        {ID: 3, Name: "Charlie"},
    }
    
    orders := []Order{
        {ID: 101, CustomerID: 1, Product: "Laptop", Amount: 999.99},
        {ID: 102, CustomerID: 1, Product: "Mouse", Amount: 29.99},
        {ID: 103, CustomerID: 2, Product: "Keyboard", Amount: 79.99},
        {ID: 104, CustomerID: 3, Product: "Monitor", Amount: 299.99},
        {ID: 105, CustomerID: 1, Product: "Headphones", Amount: 149.99},
    }
    
    // 方法1:使用Map索引
    fmt.Println("=== 使用Map索引 ===")
    orderIndex := make(map[int][]Order)
    for _, order := range orders {
        orderIndex[order.CustomerID] = append(orderIndex[order.CustomerID], order)
    }
    
    for _, cust := range customers {
        if custOrders, exists := orderIndex[cust.ID]; exists {
            fmt.Printf("%s's orders:\n", cust.Name)
            for _, order := range custOrders {
                fmt.Printf("  - %s: $%.2f\n", order.Product, order.Amount)
            }
        }
    }
    
    // 方法2:使用二分查找
    fmt.Println("\n=== 使用二分查找 ===")
    sort.Slice(orders, func(i, j int) bool {
        return orders[i].CustomerID < orders[j].CustomerID
    })
    
    customerID := 1
    start := sort.Search(len(orders), func(i int) bool {
        return orders[i].CustomerID >= customerID
    })
    
    if start < len(orders) && orders[start].CustomerID == customerID {
        end := start
        for end < len(orders) && orders[end].CustomerID == customerID {
            end++
        }
        fmt.Printf("Customer %d has %d orders\n", customerID, end-start)
    }
}

性能对比

  • Map索引:建立索引O(n),查询O(1),适合多次查询
  • 二分查找:排序O(n log n),查询O(log n),适合数据不经常变动
  • 线性搜索:查询O(n),适合小数据集或单次查询

对于数据库查询结果的处理,建议使用Map建立索引,特别是当需要多次查询时,可以显著提高性能。

回到顶部