Go – List

5/5 - (1 vote)

Trong phần này chúng ta sẽ tìm hiểu về kiểu dữ liệu List trong Go.

Ngoài các kiểu dữ liệu dạng danh sách mà chúng ta đã tìm hiểu như array, slice và map, Go còn cung cấp một kiểu dữ liệu khác là List có trong gói container/list.

List

Kiểu List Gói container/list thực chất chính là cấu trúc Danh sách liên kết đôi, nếu bạn đã từng học môn Cấu trúc dữ liệu ở Đại học thì sẽ biết cấu trúc này.

Capture

Danh sách liên kết là một danh sách các biến struct kiểu Node do chúng ta tự định nghĩa, các biến Node này có các trường dữ liệu thông thường (như int, float, string...) và một trường đặc biệt là một con trỏ kiểu Node, con trỏ này lưu địa chỉ của Node tiếp theo trong danh sách.

Danh sách liên kết đôi thì mỗi Node chứa 2 con trỏ, một con trỏ chỉ tới Node phía sau nó và một con trỏ chỉ tới Node phía trước nó.

Danh sách liên kết cho phép chúng ta sử dụng bộ nhớ máy tính một cách linh hoạt hơn.

Trong Go thì chúng ta có thể sử dụng struct List đã được định nghĩa sẵn như sau:

package main

import "fmt"
import "container/list"

func main() {
    var x list.List
 
    x.PushBack(1)
    x.PushBack(2.5)
    x.PushBack("Hello")

    for e := x.Front() ; e != nil ; e = e.Next() {
        fmt.Println(e.Value)
    }
}

Trong đoạn code trên, chúng ta tạo một biến List là x, khi tạo thì x rỗng, không có phần tử nào cả.

x.PushBack(1)
x.PushBack(2.5)
x.PushBack("Hello")

Chúng ta thêm một phần tử vào List bằng hàm PushBack(), chúng ta có thể đưa vào bất cứ kiểu dữ liệu gì cũng được, từ int, float cho tới string... hoặc một struct do chúng ta tự tạo cũng được.

for e := x.Front() ; e != nil ; e = e.Next() 

Để lặp qua một list thì chúng ta có thể dùng vòng lặp for như trong ví dụ, hàm Front() sẽ trả về phần tử đầu tiên của list, hàm Next() sẽ trả về phần tử tiếp theo trong list, chúng ta kiểm tra cho đến khi không còn phần tử nào nữa (nil) thì vòng lặp dừng.

fmt.Println(e.Value)

Để lấy giá trị mà phần tử đang lưu trữ thì chúng ta đọc trường Value là được.

1
2.5
Hello

Sort

Trong Go có gói sort chứa các hàm hỗ trợ sắp xếp các danh sách với các kiểu dữ liệu thường dùng. Ví dụ:

package main

import "fmt"
import "sort"

func main() {

    x := []int{93, 48, 27, 784, 13}
    fmt.Println(x)
    sort.IntSlice.Sort(x)
    fmt.Println(x)
 
    y := []float64{3.5, 7.6, 8.93, 5.23, 7.609}
    fmt.Println(y)
    sort.Float64Slice.Sort(y)
    fmt.Println(y)
}

Trong đoạn code trên chúng ta có 2 slice xy, slice x chứa các phần tử kiểu int, slice y chứa các phần tử kiểu float64.

sort.IntSlice.Sort(x)
...
sort.Float64Slice.Sort(y)

Gói sort có 2 struct là IntSliceFloat64Slice, 2 struct này có hàm Sort()  có chức năng sắp xếp các phần tử trong một slice kiểu int hoặc kiểu float64.

[93 48 27 784 13]
[13 27 48 93 784]
[3.5 7.6 8.93 5.23 7.609]
[3.5 5.23 7.6 7.609 8.93]

Trong trường hợp chúng ta muốn sắp xếp các kiểu dữ liệu “không thường dùng” như struct mà chúng ta tự định nghĩa, thì chúng ta làm như sau:

package main

import "fmt"
import "sort"

type Person struct {
    Name string
    Age int
}

type ByName []Person

func (this ByName) Len() int {
    return len(this)
}
func (this ByName) Less(i, j int) bool {
    return this[i].Name < this[j].Name
}
func (this ByName) Swap(i, j int) {
     this[i], this[j] = this[j], this[i]
}
func main() {
    kids := []Person{
        {"Jill", 9},
        {"Jack", 10},
    }
    sort.Sort(ByName(kids))
    fmt.Println(kids)
}

Để một slice kiểu struct mới có thể sắp xếp được bằng hàm Sort() thì slice đó phải có 3 phương thức là Len(), Less()Swap(). Trong đó phương thức Len() trả vể số lượng phần tử của slice, Less() so sánh 2 phần tử i và j cái nào bé hơn, Swap() đổi chỗ 2 phần tử i và j cho nhau. Chẳng hạn như trong đoạn code trên chúng ta định nghĩa một struct có tên Person và một slice kiểu Person có tên ByName. Struct Person có 2 trường là NameAge, slice ByName có 3 phương thức Len(), Less()Swap(). Hàm Less() so sánh 2 phần tử bé hơn bằng cách so sánh trường Name của mỗi phần tử đó.

[{Jack 10} {Jill 9}]

Nếu muốn sắp xếp theo trường Age thì chúng ta cũng làm tương tự với hàm Less():

func (this ByName) Less(i, j int) bool {
    return this[i].Age < this[j].Age
}
5 2 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments