Есть ли пакет golang, который эквивалентен ChainMap в Python? - PullRequest
0 голосов
/ 25 марта 2019

Python ChainMap позволяет вам связать воедино несколько карт, так что поиск просматривает все карты последовательно, пока не будет найден соответствующий ключ. Вот одна из многих статей об этом:

https://dzone.com/articles/python-201-what-is-a-chainmap

И официальная документация:

https://docs.python.org/3/library/collections.html

Кто-нибудь знает о существующем эквивалентном пакете, написанном на Go? Я до сих пор не смог найти его и хотел бы не изобретать велосипед, если он существует.

Ответы [ 2 ]

1 голос
/ 25 марта 2019

Нет пакета, но довольно просто реализовать нечто подобное:

Давайте сделаем это с map[string]interface{}

package main

import (
        "reflect"
        "testing"
)

type ChainMap struct {
        Map  map[string]interface{}
        maps []map[string]interface{}
}

func NewChainMap(maps ...map[string]interface{}) ChainMap {
        if len(maps) == 0 {
                return ChainMap{
                        Map:  make(map[string]interface{}, 0),
                        maps: maps,
                }
        }
        r := make(map[string]interface{}, len(maps[0]))
        for i := len(maps) - 1; i >= 0; i-- {
                m := maps[i]
                for k, v := range m {
                        r[k] = v
                }
        }
        return ChainMap{
                Map:  r,
                maps: maps,
        }
}

func (c ChainMap) Parents() ChainMap {
        if len(c.maps) < 2 {
                return c
        }
        return NewChainMap(c.maps[1:]...)
}

Небольшой тест:

func TestChainMap(t *testing.T) {
        var m = NewChainMap(
                map[string]interface{}{
                        "foo": "bar",
                },
                map[string]interface{}{
                        "foo":   "baz",
                        "hello": "world",
                },
                map[string]interface{}{
                        "foo": "baw",
                },
        )
        if !reflect.DeepEqual(
                m.Map,
                map[string]interface{}{
                        "foo":   "bar",
                        "hello": "world",
                },
        ) {
                t.Fail()
        }

        if !reflect.DeepEqual(
                m.Parents().Map,
                map[string]interface{}{
                        "foo":   "baz",
                        "hello": "world",
                },
        ) {
                t.Fail()
        }
}
0 голосов
/ 28 марта 2019

В конце концов я нашел реализацию, похороненную в пакете bigkevmcd / go-configparser: https://github.com/bigkevmcd/go-configparser/blob/master/chainmap/chainmap.go

Достоинством этого является то, что он использует оригинальные карты для хранения, так же как и правильное, если одна из них будет обновлена ​​позже; это делает его более похожим на оригинальную версию Python. Недостатком является то, что вызывающая сторона должна вызывать функции Get () и Len (), а не просто использовать объект в качестве карты нормалей.

package chainmap

type Dict map[string]string

type ChainMap struct {
    maps []Dict
}

func New(dicts ...Dict) *ChainMap {
    chainMap := &ChainMap{
        maps: make([]Dict, 0),
    }

    for _, dict := range dicts {
        chainMap.maps = append(chainMap.maps, dict)
    }
    return chainMap
}

func (c *ChainMap) Len() int {
    return len(c.maps)
}

func (c *ChainMap) Get(key string) string {
    var value string

    for _, dict := range c.maps {
        if result, present := dict[key]; present {
            value = result
        }
    }
    return value
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...