2014-10-25 5 views
3

Я не могу найти хороший способ сделать это. Я хочу иметь карту из списка отсортированных пар ключ-значение.Использование массива переменной длины в качестве ключа карты в golang

type Tag struct { 
    key string 
    value string 
} 

type SortedTag []Tag // sorted list of tags. 
map[SortedTags]T // cannot do. 

я могу решить эту проблему путем объединения всех пар ключ-значение с разделителем, но я чувствую, что это неэффективно и подвержено ошибкам во многих отношениях. Преобразование обратно в пару «ключ-значение» громоздко, потому что нам нужно разбить вход. кроме того, если пара значений ключей может быть чем угодно, это означает, что мы должны ее избежать.

Если бы это был python, я бы сохранил Tag как N-кортеж отсортированного 2-tupless.

Если это Java, я бы создал композитный объект с Map<String,String> с equals() проверки против другой хэш-карта, hashCode() возвращая xor всех хэшей карте (xor, поскольку она является коммутативной, таким образом, мы можем итерируем карту в любом порядке, чтобы вычислить это значение).

В go, я не могу придумать другой хороший способ.

+0

Я не понимаю ваш вопрос ... Во-первых, я думаю, что неважно, отсортирован ли ваш список или нет, если вы хотите сделать карту из списка. Тогда я не понимаю тип вашей карты. Почему это не 'map [string] string'? И, наконец, почему бы не перебрать все элементы в списке и сохранить их на карте? – akonsu

+0

Ответы. * У меня есть отсортированная карта, потому что я хочу проверить, что список пар ключ-значение равен, и лучший способ убедиться, что когда примитив типа 'set' не сортирует их по ключу. * Я НЕ хочу, чтобы это была строка 'map [string] из-за причины, которую я привел ниже. * Я не понимаю ваш третий вопрос. –

+0

Насколько я понимаю, вы не хотите искать свой список по ключу, вам нужно только проверить, имеет ли он уже определенную пару ключ/значение. Правильно? В моем третьем вопросе я предположил, что проблема состоит в том, чтобы построить карту из списка. – akonsu

ответ

2

Например,

package main 

import "fmt" 

type Tag struct { 
    Key string 
    Value string 
} 

type Tags []Tag 

type TagsValue struct { 
    // some type used as Tags value 
} 

type TagsMapValue struct { 
    Tags 
    TagsValue 
} 

type TagsMapKey string 

type TagsMap map[TagsMapKey]TagsMapValue 

func NewTagsMapKey(tags Tags) TagsMapKey { 
    b := []byte{} 
    for _, tag := range tags { 
     b = append(b, tag.Key...) 
     b = append(b, tag.Value...) 
    } 
    return TagsMapKey(b[:len(b)]) 
} 

func (m *TagsMap) AddElement(tags Tags, tagsValue TagsValue) { 
    mapKey := NewTagsMapKey(tags) 
    mapValue := TagsMapValue{Tags: make(Tags, 0, len(tags)), TagsValue: tagsValue} 
    i := 0 
    for _, tag := range tags { 
     key := string(mapKey[i : i+len(tag.Key)]) 
     i += len(tag.Key) 
     value := string(mapKey[i : i+len(tag.Value)]) 
     i += len(tag.Value) 
     mapValue.Tags = append(mapValue.Tags, Tag{Key: key, Value: value}) 
    } 
    (*m)[mapKey] = mapValue 
    return 
} 

func main() { 
    m := make(TagsMap) 
    sortedTags := Tags{ 
     {Key: "key1", Value: "value1"}, 
     {Key: "key7", Value: "value7"}, 
     {Key: "key7", Value: "value49"}, 
     {Key: "key42", Value: "value42"}, 
    } 
    m.AddElement(sortedTags, TagsValue{}) 
    for k, v := range m { 
     fmt.Println("Tags Key:", k) 
     fmt.Println(" Tags:  ", v.Tags) 
     fmt.Println(" Tags Value:", v.TagsValue) 
    } 
} 

Выход:

Tags Key: key1value1key7value7key7value49key42value42 
    Tags:  [{key1 value1} {key7 value7} {key7 value49} {key42 value42}] 
    Tags Value: {} 

Если вы просто пытаетесь проверить теги установить членство,

package main 

import "fmt" 

type Tag struct { 
    Key string 
    Value string 
} 

type Tags []Tag 

type TagsSetKey string 

type TagsSet map[TagsSetKey]Tags 

func NewTagsSetKey(tags Tags) TagsSetKey { 
    b := []byte{} 
    for _, tag := range tags { 
     b = append(b, tag.Key...) 
     b = append(b, tag.Value...) 
    } 
    return TagsSetKey(b[:len(b)]) 
} 

func (m *TagsSet) AddElement(tags Tags) { 
    setKey := NewTagsSetKey(tags) 
    setValue := make(Tags, 0, len(tags)) 
    i := 0 
    for _, tag := range tags { 
     key := string(setKey[i : i+len(tag.Key)]) 
     i += len(tag.Key) 
     value := string(setKey[i : i+len(tag.Value)]) 
     i += len(tag.Value) 
     setValue = append(setValue, Tag{Key: key, Value: value}) 
    } 
    (*m)[setKey] = setValue 
    return 
} 

func (m *TagsSet) IsMember(tags Tags) bool { 
    return (*m)[NewTagsSetKey(tags)] != nil 
} 

func main() { 
    m := make(TagsSet) 
    sortedTags := Tags{ 
     {Key: "key1", Value: "value1"}, 
     {Key: "key7", Value: "value7"}, 
     {Key: "key7", Value: "value49"}, 
     {Key: "key42", Value: "value42"}, 
    } 
    m.AddElement(sortedTags) 
    for k, v := range m { 
     fmt.Println("Tags Key:", k) 
     fmt.Println(" Tags: ", v) 
    } 
    // In set 
    fmt.Println(m.IsMember(sortedTags)) 
    // Not in set 
    sortedTags[0].Key = "key0" 
    fmt.Println(m.IsMember(sortedTags)) 
} 

Выход:

Tags Key: key1value1key7value7key7value49key42value42 
    Tags: [{key1 value1} {key7 value7} {key7 value49} {key42 value42}] 
true 
false 
Смежные вопросы