Неоднозначность в Hashmap? - PullRequest
       82

Неоднозначность в Hashmap?

0 голосов
/ 08 ноября 2019

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

string s  = "dvd";
for(int i = 0;i < s.size();i++){
        if(!map[s[i]]){
            cout<<s[i];
            map[s[i]] = i;
        }
    }

, вывод будет

d v d

Мой вопрос, поскольку d уже есть в карте, так почему код печатает его снова? И еще одна интересная вещь: когда я запускаю этот код

    string s = "dvd";

    unordered_map<char,int>map;
    for(auto i :s){
        if(!map[i]){
            cout<<i<<" ";
            map[i] = i;
        }    
    }

, он дает ожидаемый результат, который равен

d v

Что мне здесь не хватает ??

1 Ответ

0 голосов
/ 08 ноября 2019

На самом деле довольно легко объяснить, что происходит, если вы понимаете, что целое число 0 преобразуется в логическое значение false (и все ненулевое значение равно true), и как ранжируется for цикл работы .


Если мы начнем с первого цикла:

for(int i = 0;i < s.size();i++){
    if(!map[s[i]]){
        cout<<s[i];
        map[s[i]] = i;
    }
}

Здесь переменная i представляет индекс символы в строке. Индексы будут (по порядку) 0, 1 и 2.

. На первой итерации 'd' не существует, поэтому map[s[i]] создаст элемент снулевое значение и вернуть нулевое значение. Это делает условие равным !0, которое является истинным, поэтому вы печатаете символ, а затем назначаете индекс 0 на map['d'] (который уже равен 0).

Вторая итерация такая же, но вы присваиваете значение 1 map['v'].

Затем вы попадаете на третью итерацию, где map['d'] уже существует. Но , поскольку значение равно 0 ваше состояние считает, что оно не существует.

Таким образом, ваше состояние имеет недостатки. Чтобы проверить, не существует ли ключ, используйте count

if (map.count(s[i]) == 0)

Или вы можете использовать find

if (map.find(s[i]) == map.end())

Или когда приходит C ++ 20, вы можете использовать contains

if (map.contains(s[i]))

Затем второй цикл:

for(auto i :s){
    if(!map[i]){
        cout<<i<<" ";
        map[i] = i;
    }    
}

Здесь iэто не индекс, это символ . Таким образом, значения, которые вы назначаете элементам карты с map[i] = i, не будут 0, 1 или 2, это будут значения закодированных символов, которые для ASCII будут 100 для символа 'd' и118 для 'v'.

Таким образом, на первой итерации map[i] будет равно нулю (как и раньше), но затем вы присваиваете 100 этому элементу.

Во второйитерация такая же, но вы присваиваете значение 118.

Теперь мы возвращаемся к букве 'd' со значением 100. Когда вы проверяете map['d'] во второй раз, значение не равно нулю, и у вас есть !100, что составляет false.

...