2017-03-09 4 views
5

मुझे समझ नहीं आता क्यों मैं कुंजी प्रकार के रूप में एक array<int,3> के साथ एक unordered_map नहीं कर सकते हैं:कुंजी के रूप में सरणियों के साथ एक unordered_map का उपयोग

#include <unordered_map> 

using namespace std; 

int main() { 

    array<int,3> key = {0,1,2}; 

    unordered_map< array<int,3> , int > test; 
    test[key] = 2; 

    return 0; 
} 

मैं एक लंबे त्रुटि मिलती है, सबसे उचित हिस्सा होने

main.cpp:11:9: error: no match for ‘operator[]’ (operand types are std::unordered_map<std::array<int, 3ul>, int>’ and ‘std::array<int, 3ul>’) 
test[key] = 2; 
    ^

क्या सरणी कुंजी होने के योग्य नहीं हैं क्योंकि उन्हें कुछ आवश्यकताएं याद आती हैं?

+1

मुझे एक त्रुटि मिल रही है जिसमें सरणी के लिए कोई हैश फ़ंक्शन नहीं है। मुझे लगता है कि यह उम्मीद की जाती है और आपको एक को लागू करना चाहिए।_ "त्रुटि: कॉल के लिए कोई मिलान नहीं है '(const std :: हैश >) (const std :: array और)'" _ जीसीसी 5.1.0 –

+0

उन सभी लोगों के लिए धन्यवाद जिन्होंने कमी की कमी की सरणी के लिए एक हैश समारोह। मैंने मूर्खता से सोचा कि यह एक बहुत ही आम बात है, उदाहरण के लिए एक स्पैर मैट्रिक्स स्टोर करने के लिए (मैं यहां क्या कर रहा हूं)। – Adrien

उत्तर

8

क्यों?

अपने प्रश्न हम hash एक सरणी जो मानक C++ आंतरिक रूप से लागू नहीं किया गया करने की आवश्यकता के अनुसार http://www.cplusplus.com/reference/unordered_map/unordered_map/

Internally, the elements in the unordered_map are not sorted in any particular order with respect to either their key or mapped values, but organized into buckets depending on their hash values to allow for fast access to individual elements directly by their key values (with a constant average time complexity on average).

में उल्लेख किया है अब।

इसके साथ कैसे प्राप्त करें?

तो तुम जिसके लिए आप C++ how to insert array into hash set? से कुछ मदद मिल सकती है आप अपने खुद के एसटीडी को लागू करना चाहिए एक मूल्य :: हैश http://en.cppreference.com/w/cpp/utility/hash के लिए एक array मैप करने के लिए चाहते हैं।

कुछ काम के आसपास

आप boost उपयोग करने के लिए तो यह सरणियों और कई अन्य प्रकार के हैशिंग प्रदान कर सकते हैं नि: शुल्क कर रहे हैं। यह मूल रूप से hash_combine विधि का उपयोग करता है जिसके लिए आप http://www.boost.org/doc/libs/1_49_0/boost/functional/hash/hash.hpp पर एक नज़र डाल सकते हैं।

"The C++ Standard doesn't provide a hash for this type."

मुझे लगता है कि यह स्वतः स्पष्ट है:

8

प्रासंगिक त्रुटि

error: no match for call to '(const std::hash<std::array<int, 3ul> >) (const std::array<int, 3ul>&)'

unordered_map कुंजी के हैश की जरूरत है, और यह std::hash की एक अधिभार ऐसा करने के लिए लग रहा है। आप उपयुक्त हैश फ़ंक्शन के साथ namespace std का विस्तार कर सकते हैं।

1

msvc14 साथ संकलित निम्न त्रुटि देता है।

5

आपको एक हैश लागू करना होगा। कुंजी को हैश करने के आधार पर हैश टेबल, उन्हें रखने के लिए बाल्टी खोजने के लिए। C++ जादूगर रूप से यह नहीं जानता कि हर प्रकार हैश कैसे है, और इस विशेष मामले में यह नहीं जानता कि डिफ़ॉल्ट रूप से 3 पूर्णांकों की सरणी कैसे है। आप इस प्रकार का सरल हैश struct को लागू कर सकते हैं:

struct ArrayHasher { 
    std::size_t operator()(const std::array<int, 3>& a) { 
     std::size_t h = 0; 

     for (auto e : a) { 
      h ^= std::hash<int>{}(e) + 0x9e3779b9 + (h << 6) + (h >> 2); 
     } 
     return h; 
    } 
}; 

और फिर इसका इस्तेमाल:

unordered_map< array<int,3> , int, ArrayHasher > test; 

संपादित करें: मैं के लिए बढ़ावा द्वारा इस्तेमाल किया कार्य करने के लिए, एक अनुभवहीन XOR से हैश के संयोजन के लिए समारोह बदल यह उद्देश्य: http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html। यह वास्तव में उपयोग करने के लिए पर्याप्त मजबूत होना चाहिए।

+0

बहुत बहुत धन्यवाद। हाँ, मुझे हैश फ़ंक्शन के बारे में बहुत कुछ पता नहीं है और क्या एक अच्छा हैश फ़ंक्शन बनाता है, इसलिए मुझे लगता है कि मैं बस ऑर्डर किए गए मानचित्रों पर जाउंगा और अतिरिक्त लॉग जटिलता का समय भुगतूंगा! – Adrien

+0

@Adrien अच्छी तरह से आदेशित नक्शे के साथ सबसे बड़ा हिट संभवतः लॉगएन समय नहीं है, लेकिन वास्तव में खराब कैश कोहेरेंसी है। इसके अलावा, हैश अच्छी तरह से संयोजन एक सरल सूत्र के साथ किया जा सकता है; मेरे जवाब में संपादन देखें। आपको उपरोक्त कोड का उपयोग अपने प्रोजेक्ट में करने में सक्षम होना चाहिए। –

संबंधित मुद्दे