Удалить дубликаты с карты срезов - PullRequest
1 голос
/ 29 октября 2019

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

Ожидаемый результат: map[key1:[1 2 3] key2:[1 2 3]]

Фактический результат: map[key2:[1 2 3]]

    package main

    import "fmt"

    func main() {
        x := make(map[string][]string)
        keys := make(map[string]bool)
        result := make(map[string][]string)

        x["key1"] = append(x["key1"], "1")
        x["key1"] = append(x["key1"], "1")
        x["key1"] = append(x["key1"], "2")
        x["key1"] = append(x["key1"], "3")
        x["key1"] = append(x["key1"], "3")
        x["key2"] = append(x["key2"], "1")
        x["key2"] = append(x["key2"], "2")
        x["key2"] = append(x["key2"], "2")
        x["key2"] = append(x["key2"], "3")

        fmt.Println(x)

        for k, e := range x{
            for _, v := range e {
                if _, val := keys[v]; !val {
                    keys[v] = true
                    result[k] = append(result[k], v)
                }
            }
        }
        fmt.Println(result)
    }

Пример на детской площадке здесь: Go Playground

1 Ответ

1 голос
/ 29 октября 2019

Вы хотите, чтобы все кусочки обрабатывались отдельно. Например, вы хотите удалить дубликаты из фрагмента, обозначенного x["key1"], и хотите удалить дубликаты из фрагмента, обозначенного x["key2"]. Это означает, что вы должны «сбросить» keys, когда обрабатывается новый фрагмент, но вы инициализируете его только один раз.

Как следствие, если (по какой-либо случайности) вы сначала обрабатываете x["key1"], а затемвы переходите к x["key2"], поскольку x["key1"] содержит все элементы, которые есть в x["key2"], новые элементы не будут найдены, поэтому "key2" будет полностью исключен из результата.

Просто инициализируйте keys перед каждым срезом внутри цикла:

for k, e := range x {
    keys := make(map[string]bool)
    for _, v := range e {
        if _, val := keys[v]; !val {
            keys[v] = true
            result[k] = append(result[k], v)
        }
    }
}

При этом вывод будет (попробуйте на Go Playground ):

map[key1:[1 1 2 3 3] key2:[1 2 2 3]]
map[key1:[1 2 3] key2:[1 2 3]]

Также обратите внимание, что вы можете использовать составной литерал для создания вашей начальной карты таким компактным образом, как это:

x := map[string][]string{
    "key1": {"1", "1", "2", "3", "3"},
    "key2": {"1", "2", "2", "3"},
}

И так как вы используете bool в вашей keys карте,вы можете просто проверить наличие существующих элементов, как это (потому что индексирование карты с ключом, которого нет в ней, приводит к нулевому значению типа значения карты, которое для bool равно false, правильно говоря, элемент не находится вкарта):

if !keys[v] {
    keys[v] = true
    result[k] = append(result[k], v)
}

Попробуйте это на GoДетская площадка .

Подробнее об этом можно прочитать здесь: Как проверить, есть ли на карте ключ в Go? Как создать массив, содержащий уникальные строки?

...