วิธีประกาศแผนที่คงที่


126

ฉันพยายามประกาศว่าจะคงที่ใน Go แต่เกิดข้อผิดพลาด ใครช่วยฉันเกี่ยวกับไวยากรณ์ของการประกาศค่าคงที่ใน Go ได้ไหม

นี่คือรหัสของฉัน:

const romanNumeralDict map[int]string = {
  1000: "M",
  900 : "CM",
  500 : "D",
  400 : "CD",
  100 : "C",
  90  : "XC",
  50  : "L",
  40  : "XL",
  10  : "X",
  9   : "IX",
  5   : "V",
  4   : "IV",
  1   : "I",
}

นี่คือข้อผิดพลาด

# command-line-arguments
./Roman_Numerals.go:9: syntax error: unexpected {

คำตอบ:


154

ไวยากรณ์ของคุณไม่ถูกต้อง ในการสร้างแผนที่ตามตัวอักษร (เป็นค่าคงที่หลอก) คุณสามารถทำได้:

var romanNumeralDict = map[int]string{
  1000: "M",
  900 : "CM",
  500 : "D",
  400 : "CD",
  100 : "C",
  90  : "XC",
  50  : "L",
  40  : "XL",
  10  : "X",
  9   : "IX",
  5   : "V",
  4   : "IV",
  1   : "I",
}

ภายในfuncคุณสามารถประกาศได้เช่น:

romanNumeralDict := map[int]string{
...

และใน Go ไม่มีสิ่งที่เรียกว่าแผนที่คงที่ ข้อมูลเพิ่มเติมสามารถพบได้ที่นี่

ลองใช้ใน Go playground


1
สิ่งนี้พ่นnon-declaration statement outside function bodyเวลาคอมไพล์จริง มาได้ยังไง?
alediaferia

@AlessandroDiaferia ฉันไม่ได้รับข้อผิดพลาดดังกล่าว คุณใช้มันอย่างไร?
squiguy

7
@AlessandroDiaferia ลองด้วยvar romanNumeralDict map[int]string = map[int]string{...}ในกรณีนี้
B-Scan

4
@alediaferia คุณจะได้รับข้อผิดพลาดนั้นหากใช้:=นอกฟังก์ชัน
Jeffrey Martinez

1
"ค่าคงที่หลอก" คืออะไร?
Garrett

23

คุณสามารถสร้างค่าคงที่ได้หลายวิธี:

const myString = "hello"
const pi = 3.14 // untyped constant
const life int = 42 // typed constant (can use only with ints)

คุณยังสามารถสร้างค่าคงที่ enum:

const ( 
   First = 1
   Second = 2
   Third = 4
)

คุณไม่สามารถสร้างค่าคงที่ของแผนที่อาร์เรย์และเขียนด้วยวิธีการที่มีประสิทธิภาพ :

ค่าคงที่ใน Go เป็นเพียงค่าคงที่ พวกมันถูกสร้างขึ้นในเวลาคอมไพล์แม้ว่าจะถูกกำหนดให้เป็นโลคัลในฟังก์ชันและสามารถเป็นตัวเลขอักขระ (รูน) สตริงหรือบูลีนเท่านั้น เนื่องจากข้อ จำกัด เวลาคอมไพล์นิพจน์ที่กำหนดต้องเป็นนิพจน์คงที่ซึ่งคอมไพเลอร์ประเมินได้ ตัวอย่างเช่น 1 << 3 เป็นนิพจน์คงที่ในขณะที่ math.Sin (math.Pi / 4) ไม่ใช่เพราะฟังก์ชันเรียกใช้คณิตศาสตร์ Sin ต้องเกิดขึ้นในขณะรันไทม์


ดังนั้นมันจึงเหมือน C ++ 11 constexpr มากกว่า ... ทำไมคณิตศาสตร์ Sin ไม่ใช่ฟังก์ชัน constexpr แล้วล่ะ!
Francesco Dondi

ข้อความของคุณถูกต้อง แต่คำถามเกี่ยวกับการสร้างแผนที่ที่คงที่
jzer7

5
@ jzer7 ช่วยอธิบายหน่อยได้ไหมว่าทำไมคำตอบของฉันถึงไม่เกี่ยวข้อง เขาถามว่าจะสร้างอะไรผมบอกเขาว่ามันเป็นไปไม่ได้ อธิบายถึงสิ่งที่เป็นไปได้และให้คำอ้างอิงจากเอกสารว่าเหตุใดจึงไม่สามารถทำสิ่งที่เขาต้องการได้
Salvador Dali

12

คุณสามารถจำลองแผนที่ด้วยการปิด:

package main

import (
    "fmt"
)

// http://stackoverflow.com/a/27457144/10278

func romanNumeralDict() func(int) string {
    // innerMap is captured in the closure returned below
    innerMap := map[int]string{
        1000: "M",
        900:  "CM",
        500:  "D",
        400:  "CD",
        100:  "C",
        90:   "XC",
        50:   "L",
        40:   "XL",
        10:   "X",
        9:    "IX",
        5:    "V",
        4:    "IV",
        1:    "I",
    }

    return func(key int) string {
        return innerMap[key]
    }
}

func main() {
    fmt.Println(romanNumeralDict()(10))
    fmt.Println(romanNumeralDict()(100))

    dict := romanNumeralDict()
    fmt.Println(dict(400))
}

ลองใช้ใน Go playground


4
(TestMostSoldRecommender?)
twotwotwo

1
ในความเป็นจริงเป็นทางออกที่เป็นไปได้ อย่างไรก็ตามเนื่องจากผู้เขียนไม่ได้อธิบายอะไรเลย (และใส่ทุกอย่างไว้ในกรณีทดสอบที่มีชื่อแปลก ๆ ) คำตอบจึงดูไม่ถูกต้อง ตรรกะคือ: (1) สร้างฟังก์ชันที่ไม่ระบุตัวตน (2) ฟังก์ชันที่ไม่ระบุชื่อจะห่อหุ้มmap(3) ฟังก์ชันที่ไม่ระบุชื่อจะส่งกลับ "ฟังก์ชันที่ยอมรับ int และส่งคืนสตริง" (4) ฟังก์ชันที่ส่งคืนทำสตริง int -> การทำแผนที่โดยใช้map(5) เรียกใช้ฟังก์ชันนิรนามทันทีและกำหนดฟังก์ชันที่ส่งคืนให้กับตัวแปร ตัวแปรนี้สามารถใช้เหมือนฟังก์ชันและเอฟเฟกต์ก็เหมือนกับแผนที่
Siu Ching Pong -Asuka Kenji-

3

และตามที่แนะนำไว้ข้างต้นโดยซิวจิงปง -Asuka Kenjiพร้อมฟังก์ชั่นที่ในความคิดของฉันเหมาะสมกว่าและทำให้คุณสะดวกในการใช้ประเภทแผนที่โดยไม่ต้องมีสิ่งห่อหุ้มฟังก์ชัน:

   // romanNumeralDict returns map[int]string dictionary, since the return
       // value is always the same it gives the pseudo-constant output, which
       // can be referred to in the same map-alike fashion.
       var romanNumeralDict = func() map[int]string { return map[int]string {
            1000: "M",
            900:  "CM",
            500:  "D",
            400:  "CD",
            100:  "C",
            90:   "XC",
            50:   "L",
            40:   "XL",
            10:   "X",
            9:    "IX",
            5:    "V",
            4:    "IV",
            1:    "I",
          }
        }

        func printRoman(key int) {
          fmt.Println(romanNumeralDict()[key])
        }

        func printKeyN(key, n int) {
          fmt.Println(strings.Repeat(romanNumeralDict()[key], n))
        }

        func main() {
          printRoman(1000)
          printRoman(50)
          printKeyN(10, 3)
        }

ลองดูที่ play.golang.org


-2

ตามที่ระบุไว้ข้างต้นเพื่อกำหนดแผนที่เป็นค่าคงที่เป็นไปไม่ได้ แต่คุณสามารถประกาศตัวแปรส่วนกลางซึ่งเป็นโครงสร้างที่มีแผนที่

การเริ่มต้นจะมีลักษณะดังนี้:

var romanNumeralDict = struct {
    m map[int]string
}{m: map[int]string {
    1000: "M",
    900: "CM",
    //YOUR VALUES HERE
}}

func main() {
    d := 1000
    fmt.Printf("Value of Key (%d): %s", d, romanNumeralDict.m[1000])
}

3
ทำไมไม่เพียงแค่ทำให้แผนที่เป็นตัวแปรทั่วโลก? ทำไมต้องห่อไว้ในโครงสร้าง?
Hurricane Hamilton

3
สิ่งนี้ไม่ได้ทำให้แผนที่คงที่ แต่คุณยังทำได้romanNumeralDict.m[1000] = "New value"
brando
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.