2012-11-16 22 views
47

Nếu tôi có một bản đồ m là có một cách tốt hơn để nhận được một lát các giá trị v sau đóTrong golang là có một cách tốt đẹp để nhận được một lát giá trị từ một bản đồ?

package main 
import (
    "fmt" 
) 

func main() { 
    m := make(map[int]string) 

    m[1] = "a" 
    m[2] = "b" 
    m[3] = "c" 
    m[4] = "d" 

    // Can this be done better? 
    v := make([]string, len(m), len(m)) 
    idx := 0 
    for _, value := range m { 
     v[idx] = value 
     idx++ 
    } 

    fmt.Println(v) 
} 

Có một tính năng xây dựng một bản đồ? Có một chức năng trong một gói Go, hay đây là mã tốt nhất để làm nếu tôi phải làm gì?

+0

thay vì '_' ở của bạn giá trị cho vòng lặp, gọi nó là idx và mương idx ++ kinh doanh –

+0

Không, anh không thể, khi bạn nằm trong khoảng trên bản đồ nó trả chìa khóa, giá trị không chỉ mục,. Trong ví dụ của mình, anh ta sử dụng 1 làm khóa đầu tiên và điều đó sẽ làm cho các chỉ mục trong slice v không đúng vì chỉ mục bắt đầu sẽ là 1 không bằng 0 và khi nó đến 4 nó sẽ nằm ngoài phạm vi. https://play.golang.org/p/X8_SbgxK4VX – Popmedic

Trả lời

29

Thật không may, không. Không có cách nào được xây dựng để làm điều này.

Như một mặt lưu ý, bạn có thể bỏ qua đối số năng lực trong việc tạo ra miếng của bạn:

v := make([]string, len(m)) 

Năng lực được ngụ ý để được giống như chiều dài ở đây.

28

Như một sự bổ sung để bài jimt của:

Bạn cũng có thể sử dụng append hơn là gán một cách rõ ràng các giá trị để chỉ số của họ:

m := make(map[int]string) 

m[1] = "a" 
m[2] = "b" 
m[3] = "c" 
m[4] = "d" 

v := make([]string, 0, len(m)) 

for _, value := range m { 
    v = append(v, value) 
} 

Lưu ý rằng độ dài bằng không (không có yếu tố hiện tại chưa) nhưng dung lượng (không gian được phân bổ) được khởi tạo với số lượng các thành phần của m. Điều này được thực hiện để append không cần cấp phát bộ nhớ mỗi khi công suất của slice v hết.

Bạn cũng có thể make lát không có giá trị dung lượng và để append cấp phát bộ nhớ cho chính nó.

+0

Tôi đã tự hỏi nếu điều này sẽ là bất kỳ chậm hơn (giả định lên phân bổ phía trước)? Tôi đã làm một điểm chuẩn thô với một bản đồ [int] int và nó có vẻ chậm hơn khoảng 1-2%. Bất kỳ ý tưởng nếu điều này là một cái gì đó phải lo lắng hoặc chỉ cần đi với nó? – masebase

+1

Tôi giả định nối thêm một chút chậm hơn nhưng sự khác biệt đó là, trong hầu hết các trường hợp, không đáng kể. [Điểm chuẩn so sánh gán trực tiếp và nối thêm] (http://pastie.org/5393131). – nemo

0

Theo như tôi hiện đang nhận thức, đi không có cách thức để nối chuỗi/byte vào một chuỗi kết quả mà không cần tạo ít nhất hai/hai bản sao.

Bạn hiện phải tăng [] byte vì tất cả các giá trị chuỗi là const, THEN bạn phải sử dụng chuỗi nội tuyến để ngôn ngữ tạo đối tượng chuỗi 'may mắn', nó sẽ sao chép bộ đệm vì có thể có tham chiếu đến địa chỉ sao lưu byte [].

Nếu một byte [] là phù hợp thì bạn có thể đạt được một dẫn rất nhẹ qua byte.Join chức năng bằng cách thực hiện một phân bổ và làm bản sao gọi tự của bạn.

package main 
import (
    "fmt" 
) 

func main() { 
m := make(map[int]string) 

m[1] = "a" ; m[2] = "b" ;  m[3] = "c" ; m[4] = "d" 

ip := 0 

/* If the elements of m are not all of fixed length you must use a method like this; 
* in that case also consider: 
* bytes.Join() and/or 
* strings.Join() 
* They are likely preferable for maintainability over small performance change. 

for _, v := range m { 
    ip += len(v) 
} 
*/ 

ip = len(m) * 1 // length of elements in m 
r := make([]byte, ip, ip) 
ip = 0 
for _, v := range m { 
    ip += copy(r[ip:], v) 
} 

// r (return value) is currently a []byte, it mostly differs from 'string' 
// in that it can be grown and has a different default fmt method. 

fmt.Printf("%s\n", r) 
} 
Các vấn đề liên quan