Tanpa mengulangi seluruh array, bagaimana saya bisa memeriksa apakah x
dalam array menggunakan Go? Apakah bahasa memiliki konstruk?
Seperti Python: if "x" in array: ...
Tanpa mengulangi seluruh array, bagaimana saya bisa memeriksa apakah x
dalam array menggunakan Go? Apakah bahasa memiliki konstruk?
Seperti Python: if "x" in array: ...
Tidak ada operator bawaan untuk melakukannya di Go. Anda perlu beralih di atas array. Anda dapat menulis fungsi Anda sendiri untuk melakukannya, seperti ini:
func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
Jika Anda ingin dapat memeriksa keanggotaan tanpa mengulangi seluruh daftar, Anda perlu menggunakan peta sebagai ganti array atau slice, seperti ini:
visitedURL := map[string]bool {
"http://www.google.com": true,
"https://paypal.com": true,
}
if visitedURL[thisSite] {
fmt.Println("Already been here.")
}
Solusi lain jika daftar berisi nilai-nilai statis.
misalnya: memeriksa nilai yang valid dari daftar nilai yang valid:
func IsValidCategory(category string) bool {
switch category {
case
"auto",
"news",
"sport",
"music":
return true
}
return false
}
Ini adalah kutipan dari buku "Programming in Go: Membuat Aplikasi untuk Abad 21":
Menggunakan pencarian linear sederhana seperti ini adalah satu-satunya pilihan untuk data yang tidak disortir dan baik untuk irisan kecil (hingga ratusan item). Tetapi untuk irisan yang lebih besar — terutama jika kita melakukan pencarian berulang kali — pencarian linier sangat tidak efisien, rata-rata membutuhkan setengah item untuk dibandingkan setiap kali.
Go menyediakan metode sort.Search () yang menggunakan algoritma pencarian biner: Ini membutuhkan perbandingan hanya item log2 (n) (di mana n adalah jumlah item) setiap kali. Untuk menempatkan ini dalam perspektif, pencarian linear dari 10.000 item membutuhkan rata-rata 500.000 perbandingan, dengan kasus terburuk perbandingan 1000000; pencarian biner membutuhkan paling banyak 20 perbandingan, bahkan dalam kasus terburuk.
files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.Search(len(files),
func(i int) bool { return files[i] >= target })
if i < len(files) && files[i] == target {
fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}
n*log(n) + log(n)
, karena ini adalah dua operasi independen yang konsekuen
Contoh di atas menggunakan pengurutan dekat, tetapi dalam kasus string cukup gunakan SearchString:
files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.SearchStrings(files, target)
if i < len(files) && files[i] == target {
fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}
sort.SearchStrings
.
Hanya punya pertanyaan serupa dan memutuskan untuk mencoba beberapa saran di utas ini.
Saya telah membuat tolok ukur skenario kasus terbaik dan terburuk dari 3 jenis pencarian:
ini kode fungsinya:
func belongsToMap(lookup string) bool {
list := map[string]bool{
"900898296857": true,
"900898302052": true,
"900898296492": true,
"900898296850": true,
"900898296703": true,
"900898296633": true,
"900898296613": true,
"900898296615": true,
"900898296620": true,
"900898296636": true,
}
if _, ok := list[lookup]; ok {
return true
} else {
return false
}
}
func belongsToList(lookup string) bool {
list := []string{
"900898296857",
"900898302052",
"900898296492",
"900898296850",
"900898296703",
"900898296633",
"900898296613",
"900898296615",
"900898296620",
"900898296636",
}
for _, val := range list {
if val == lookup {
return true
}
}
return false
}
func belongsToSwitch(lookup string) bool {
switch lookup {
case
"900898296857",
"900898302052",
"900898296492",
"900898296850",
"900898296703",
"900898296633",
"900898296613",
"900898296615",
"900898296620",
"900898296636":
return true
}
return false
}
skenario kasus terbaik memilih item pertama dalam daftar, yang terburuk menggunakan nilai tidak ada.
berikut hasilnya:
BenchmarkBelongsToMapWorstCase-4 2000000 787 ns/op
BenchmarkBelongsToSwitchWorstCase-4 2000000000 0.35 ns/op
BenchmarkBelongsToListWorstCase-4 100000000 14.7 ns/op
BenchmarkBelongsToMapBestCase-4 2000000 683 ns/op
BenchmarkBelongsToSwitchBestCase-4 100000000 10.6 ns/op
BenchmarkBelongsToListBestCase-4 100000000 10.4 ns/op
Alihkan kemenangan, case terburuk jauh lebih cepat daripada case terbaik. Peta adalah yang terburuk dan daftar lebih dekat untuk beralih.
Jadi moralnya adalah: Jika Anda memiliki daftar statis, cukup kecil, pergantian pernyataan adalah cara untuk pergi.
:
alih - alih ,
dalam pernyataan switch? Apakah ini membuatnya lebih cepat?
case
pernyataan, bukan satu kasus. Hasilnya masuk akal sama dengan kedua fungsi.
Pilihan lain adalah menggunakan peta sebagai set. Anda hanya menggunakan kunci dan memiliki nilai menjadi sesuatu seperti boolean yang selalu benar. Kemudian Anda dapat dengan mudah memeriksa apakah peta tersebut berisi kunci atau tidak. Ini berguna jika Anda membutuhkan perilaku set, di mana jika Anda menambahkan nilai beberapa kali, itu hanya di set sekali.
Berikut adalah contoh sederhana di mana saya menambahkan angka acak sebagai kunci ke peta. Jika nomor yang sama dihasilkan lebih dari satu kali tidak masalah, itu hanya akan muncul di peta akhir satu kali. Lalu saya menggunakan cek sederhana jika untuk melihat apakah kunci ada di peta atau tidak.
package main
import (
"fmt"
"math/rand"
)
func main() {
var MAX int = 10
m := make(map[int]bool)
for i := 0; i <= MAX; i++ {
m[rand.Intn(MAX)] = true
}
for i := 0; i <= MAX; i++ {
if _, ok := m[i]; ok {
fmt.Printf("%v is in map\n", i)
} else {
fmt.Printf("%v is not in map\n", i)
}
}
}
Ini sedekat yang saya bisa rasakan secara alami oleh operator "in" Python. Anda harus menentukan tipe Anda sendiri. Kemudian Anda dapat memperluas fungsionalitas jenis itu dengan menambahkan metode seperti "memiliki" yang berperilaku seperti yang Anda harapkan.
package main
import "fmt"
type StrSlice []string
func (list StrSlice) Has(a string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
func main() {
var testList = StrSlice{"The", "big", "dog", "has", "fleas"}
if testList.Has("dog") {
fmt.Println("Yay!")
}
}
Saya memiliki perpustakaan utilitas di mana saya mendefinisikan beberapa hal umum seperti ini untuk beberapa jenis irisan, seperti yang mengandung bilangan bulat atau struct saya sendiri.
Ya, ini berjalan dalam waktu linier, tapi bukan itu intinya. Intinya adalah untuk bertanya dan mempelajari bahasa umum apa yang Go miliki dan tidak miliki. Ini latihan yang bagus. Apakah jawaban ini konyol atau berguna terserah pembaca.
strings.Index
) membantu membuatnya lebih jelas apa yang dilakukan kode. Saya mendapat kesan bahwa mungkin Anda berpikir Pythonin array:
melakukan sesuatu dengan cepat / ajaib. AFAIK tidak. Membuat loop yang eksplisit membantu membuat penulis (dan semua pembaca) sadar dan mempertimbangkan implementasi lain (misalnya peta).