ฉันชอบ google golang แต่บางคนสามารถอธิบายได้ว่าเหตุผลสำหรับผู้ใช้งานที่มีโครงสร้างข้อมูลพื้นฐานเช่นชุดจากไลบรารีมาตรฐานคืออะไร
ฉันชอบ google golang แต่บางคนสามารถอธิบายได้ว่าเหตุผลสำหรับผู้ใช้งานที่มีโครงสร้างข้อมูลพื้นฐานเช่นชุดจากไลบรารีมาตรฐานคืออะไร
คำตอบ:
เหตุผลหนึ่งที่เป็นไปได้สำหรับการละเลยนี้คือมันง่ายมากที่จะตั้งค่าโมเดลด้วยแผนที่
พูดตามตรงฉันคิดว่ามันเป็นเรื่องของการกำกับดูแลเหมือนกันอย่างไรก็ตามการดู Perl เรื่องราวก็เหมือนกันทุกประการ ใน Perl คุณจะได้รับรายชื่อและแฮชเทเบิลใน Go คุณจะได้รับอาร์เรย์ชิ้นและแผนที่ ใน Perl คุณมักใช้ hashtable สำหรับปัญหาใด ๆ และทั้งหมดที่เกี่ยวข้องกับเซต
ตัวอย่าง
เพื่อเลียนแบบชุด int ใน Go เรากำหนดแผนที่:
set := make(map[int]bool)
ในการเพิ่มบางอย่างนั้นง่ายเหมือน:
i := valueToAdd()
set[i] = true
การลบบางสิ่งเป็นเพียง
delete(set, i)
และศักยภาพที่น่าอึดอัดใจของสิ่งก่อสร้างนี้ก็ถูกแยกออกไปอย่างง่ายดาย:
type IntSet struct {
set map[int]bool
}
func (set *IntSet) Add(i int) bool {
_, found := set.set[i]
set.set[i] = true
return !found //False if it existed already
}
และลบและได้รับการสามารถกำหนดได้ในทำนองเดียวกันผมมีการดำเนินงานที่สมบูรณ์แบบที่นี่ ความไม่ลงรอยกันที่สำคัญที่นี่คือความจริงที่ว่ามันไม่มียาชื่อสามัญ อย่างไรก็ตามมันเป็นไปได้ที่จะทำเช่นนี้interface{}
ในกรณีที่คุณได้รับผลการค้นหา
map[int]bool
หนึ่งสามารถใช้map[int]struct{}
แทน ฉันชอบที่สุด
map[int]struct{}
.. struct{}
ใช้เวลา 0 ไบต์
map[int]struct{}
คุณไม่สามารถทำif mymap["key"] {
เพื่อตรวจสอบการเป็นสมาชิก Google แนะนำให้ใช้bool
(ค้นหา "ชุดสามารถนำไปใช้งานได้")
ฉันคิดว่าสิ่งนี้เกี่ยวข้องกับgolang
ความเรียบง่าย set
s เป็นประโยชน์จริงๆกับdifference
, intersection
, union
, issubset
และอื่น ๆ .. วิธีการ บางทีgolang
ทีมอาจรู้สึกว่ามันมีโครงสร้างข้อมูลมากเกินไป แต่อย่างอื่น "ชุดโง่" ที่มีเพียงadd
, contains
และremove
สามารถทำซ้ำได้อย่างง่ายดายด้วยmap
ตามที่อธิบายไว้โดย @jozefg
คำตอบก่อนหน้านี้ทำงานได้เฉพาะในกรณีที่คีย์เป็นชนิดในตัว เพื่อเติมเต็มคำตอบก่อนหน้านี้ต่อไปนี้เป็นวิธีการใช้ชุดที่องค์ประกอบเป็นชนิดที่ผู้ใช้กำหนด:
package math
// types
type IntPoint struct {
X, Y int
}
// set implementation for small number of items
type IntPointSet struct {
slice []IntPoint
}
// functions
func (p1 IntPoint) Equals(p2 IntPoint) bool {
return (p1.X == p2.X) && (p1.Y == p2.Y)
}
func (set *IntPointSet) Add(p IntPoint) {
if ! set.Contains(p) {
set.slice = append(set.slice, p)
}
}
func (set IntPointSet) Contains(p IntPoint) bool {
for _, v := range set.slice {
if v.Equals(p) {
return true
}
}
return false
}
func (set IntPointSet) NumElements() int {
return len(set.slice)
}
func NewIntPointSet() IntPointSet {
return IntPointSet{(make([]IntPoint, 0, 10))}
}
type mySet map[IntPoint]bool
ทำงานได้อย่างสมบูรณ์แบบดี ทั้งหมดที่จำเป็นชนิดที่สำคัญที่ใช้ในแผนที่คือว่ามันมี==
!=
และ ความเท่าเทียมกันของชนิด struct ถูกกำหนดไว้อย่างดีของคุณวิธีการที่ควรจะเป็นเพียงแค่Equals
p1 == p2
Contains
ใช้เวลาเชิงเส้นในขณะที่aMap[]
ใช้เวลาคงที่โดยไม่คำนึงถึงจำนวนสมาชิก ทางออกที่ดีกว่าจะสร้างคีย์ที่ไม่ซ้ำกันภายในขึ้นอยู่กับเนื้อหาของสมาชิกแต่ละคนและใช้ประโยชน์จากการสอบถามเวลาคงที่ที่map
ประเภทให้ แม้แต่โซลูชันที่เร็วขึ้นซึ่งพิจารณาพฤติกรรมแคช ฯลฯ ก็มีอยู่เช่นกัน