VGrabko
@VGrabko
Golang, Php, Js

Как удалить первый елемент из map?

У меня есть мап и время от времени я проверяю сколько ram занимает этот мап. Мне необходимо удалить из него самые старые данные (первый элемент мапа). Как это сделать правильно? (сейчас я юзаю range в 1 итерацию. )
  • Вопрос задан
  • 540 просмотров
Решения вопроса 3
@Gizmothron
delete
не нужно никаких итераций, это же не массив.
Ответ написан
@IllusionTurtle
проблема в том что у map`ов нет очередности, вот смотрите:
https://play.golang.org/p/U5iwKZvS6d

вы можете удалить элемент по его ключу через delete(map, key) НО узнать какой из них первый, если я не ошибаюсь нельзя
Ответ написан
@mantyr
Пишу много Golang кода с удовольствием:)
Обычный map не гарантирует порядок. Варианты:
  • можно сделать ordered map, но с этим окуратнее, куча подводных камней
  • можно хранить в элементах время и либо ходить по нему через range удаляя все устаревшие элементы либо делать проверку при доступе к данным, если данные устарели - удаляем.


Можно сделать чуть проще:
  • делаем ch := make(chan string, 100000)
  • далее время от времени смотрим len(ch) и если он выше ну скажем половины от того что туда может влезть (подберите имперически исходя из количества и скорости пополнения данными или высчитывайте гибко) и удаляете тот элемент что первым читается из ch


https://play.golang.org/p/sopEgcwRZC
package main

import (
	"fmt"
	"sync"
)

type Map struct {
    sync.RWMutex
    ch chan string
    d map[string]string
}

func NewMap() (m *Map) {
    m = new(Map)
    m.ch = make(chan string, 10000)
    m.d  = make(map[string]string)
    return
}

func (m *Map) Add(key, value string) {
    m.Lock()
    defer m.Unlock()
    m.check(50, true)
    m.d[key] = value
    m.ch <- key
}

func (m *Map) Get(key string) string {
    m.RLock()
    defer m.RUnlock()
    if v, ok := m.d[key]; ok {
        return v
    }
    return ""
}

func (m *Map) Check() {
    m.check(50, false)
}

func (m *Map) check(len_max int, is_lock bool) {
    ch_len := len(m.ch)
    if ch_len > len_max {
        if !is_lock {
            m.Lock()
            defer m.Unlock()
        }

        ch_len = len(m.ch)
        for i := 0; i < ch_len - len_max; i++ {
            delete(m.d, <- m.ch)
        }
    }
}

func (m *Map) Len() int {
    return len(m.ch)
}

func main() {
	m := NewMap()
	for i := 0; i < 1000; i++ {
            m.Add(fmt.Sprintf("key_%s", i), fmt.Sprintf("value_%s", i))	
	}
	fmt.Println(m.Len())
}

  • храним не более len_max элементов+1 в map, при этом удаляем сначала самые старые в порядке их добавления
  • есть проблема - если ключ был добавлен несколько раз то программа не видит что элемент обновился и всё равно его удалит как старый
  • что бы этого не происходило нужно добавлять дату в ключь и проверять, если ключ имеет другую дату (или вместо даты инкрементный счётчик) то такой элемент пропускается (мы знаем что он уже где-то есть дальше в m.ch)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы