2013-08-28 13 views
6

मान लें कि मेरे पास std::map<std::string, T> (या unordered_map) है और मैं सामग्री पर एक पुनरावर्तक/संदर्भ/सूचक से कुंजी का उपयोग करना चाहता हूं।मानचित्र कुंजी के डुप्लिकेट स्टोरेज से बचें

क्या std::string कुंजी (मानचित्र द्वारा स्वामित्व वाला एक, सामग्री ऑब्जेक्ट के अंदर एक) के दो प्रतियों के बिना ऐसा करने का कोई तरीका है? क्या कोई दूसरे का संदर्भ हो सकता है?

+1

'std :: set 'का उपयोग करने के बारे में, जहां' सी' 'टी' में संग्रहीत स्ट्रिंग की तुलना करता है? –

+0

@Daniel: लेकिन फिर मुझे लुकअप के लिए एक संपूर्ण 'टी' ऑब्जेक्ट प्रदान करना होगा, न केवल 'std :: string', सही? या 'टी' से' टी' की तुलना करने के लिए 'सी' ओवरलोड किया जा सकता है और' t' से 'std :: string' तक भी? –

+0

आह, मुझे लगता है कि सी ++ 14 किसी भी प्रकार की खोज करने के लिए एक टेम्पलेटेड 'ढूंढ' सदस्य जोड़ देगा जो 'टी'' की तुलना कर सकता है। –

उत्तर

-1

दोनों एक ही मूल्य का संदर्भ हो सकते हैं। उदाहरण के लिए:

#include <stdio.h> 
#include <string> 
#include <map> 

struct xx { std::string mykey; int value; }; 

int main (int argc, char **argv) 
{ 
    std::string      key1("the-key"); 
    std::map<std::string, xx>  map; 

    map[key1].mykey = key1; 
    map[key1].value = 13; 

    std::string &lookup_key = map[key1].mykey; 

    printf("%d\n", map[lookup_key].value); 
} 
+0

मुझे लगता है कि आप इस सवाल को गलत समझते हैं। अगर मेरे पास 'ऑटो और सामग्री = मानचित्र [key1] है; ', मुझे फिर से' सामग्री' से' key1' तक पहुंचने में सक्षम होना चाहिए। एक तरीका है सामग्री प्रकार के अंदर कुंजी की एक प्रति रखना। मैं पूछ रहा हूं कि एक प्रतिलिपि से बचने का कोई तरीका है या नहीं। –

+0

ओह, यह स्पष्ट करता है। एक ही तरीका के साथ सामग्री को खोजने के लिए पूरे संग्रह को चलाना एकमात्र तरीका होगा। या दूसरा संग्रह रखें जो मानचित्र को या तो पते, या टी – ash

+0

की कुछ अन्य सामग्री देता है, वैसे ही, यह मुझे उत्तर देने के लिए प्रेरित करता है: "क्या कोई दूसरे के संदर्भ में हो सकता है?" – ash

1

क्यों आप दो वस्तुओं बना सकता हूँ नहीं:

std::set<std::string> wordSet; 
std::map<std::string*, T> yourMap; 

टी एसटीडी सूचक शामिल होना चाहिए :: स्ट्रिंग, और yourMap कस्टम तुलनित्र की जरूरत है। इसके अतिरिक्त आप इन सभी को कुछ कक्षा में लपेट सकते हैं।

3

क्या आप boost :: bimap का उपयोग करने पर विचार करेंगे? नीचे एक साधारण उदाहरण है:

#include <boost/bimap.hpp> 
#include <string> 
struct Person 
{ 
    Person() 
    {} 
    Person(const std::string& f, const std::string& l, int a) : first(f), last(l), age(a) 
    {} 
    std::string first; 
    std::string last; 
    int age; 
}; 

bool operator <(const Person& lhs, const Person& rhs) 
{ 
    if(lhs.last < rhs.last) 
     return true; 
    return false; 
} 

std::ostream& operator << (std::ostream& os, const Person& p) 
{ 
    os << "First Name: " << p.first << " Last Name: " << p.last << " Age: " << p.age; 
    return os; 
} 

int main() 
{ 
    typedef boost::bimap<std::string, Person> people; 
    typedef people::value_type value; 

    people m; 
    m.insert(value("12345",Person("fred", "rabbit", 10))); 
    m.insert(value("67890",Person("benjamin", "bunny", 12))); 

    Person p = m.left.at("12345"); 
    std::cout << "Person with serial no. 12345 is: " << p << "\n"; 
    std::cout << "Serial number of " << p << " is: " << m.right.at(p) << "\n"; 

} 
+0

यह काम कर सकता है, लेकिन मुझे लगता है कि यह उस मामले के लिए डिज़ाइन किया गया है जहां आपके पास केवल 'mapped_type' तत्व की एक प्रति है, संभवतया संश्लेषित, प्रत्यक्ष संकेतक जैसे मेटाडेटा के बिना। –

2

कारण यह कठिन बना क्योंकि यह खतरनाक है। आपको गारंटी है कि std::string सदस्यों में से कोई भी कुंजी बंद नहीं होगा, कभी भी मूल्य नहीं बदलेगा, या पूरा नक्शा अवैध हो जाएगा। दिलचस्प, दिमाग में आने वाला पहला समाधान बेहद हैकिश दिखाई देता है, और यूबी की तरह दिखता है, लेकिन मेरा मानना ​​है कि मैं बहुत सावधानी से यूबी को स्कर्ट करता हूं।

struct key_type { 
    mutable const char* ptr;  
}; 
bool operator<(const key_type& lhs, const key_type& rhs) 
{return strcmp(lhs.ptr, rhs.ptr)<0;} 

struct person { 
    std::string name; 
    int age; 
}; 
person& people_map_get(std::map<key_type, person>& map, const char* name) { 
    auto it = map.insert(name, person{name}).first; //grab, possibly insert 
    if->first.ptr = it->second.name.c_str(); //in case of insert, fix ptr 
    return it->second; 
} 
person& people_map_assign(std::map<key_type, person>& map, person p) { 
    auto pair = map.insert(name, p); //grab, possibly insert 
    auto it = pair.first;  
    if (pair.second == false) 
     it->second = std::move(p); 
    if->first.ptr = it->second.name.c_str(); //ptr probably invalidated, so update it 
    return it->second; 
} 

int main() { 
    std::map<key_type, person> people; 
    people_map_assign(people, person{"ted"}); 
    person frank = people_map_get(people, "frank"); 
} 

मुझे आशा है कि के रूप में स्पष्ट है, इस पागल यूबी के करीब है, और बहुत ज्यादा की सलाह नहीं दी। असल में, एक डालने/खोजने के दौरान, आपके अस्थायी ऑब्जेक्ट या इनपुट स्ट्रिंग पर मुख्य बिंदु, और जैसे ही ऑब्जेक्ट डाला/पाया जाता है, कुंजी स्ट्रिंग सदस्य में निहित मान पर इंगित होती है, और जब तक आप कभी भी ऐसा कुछ भी नहीं करते हैं जो किसी भी person ऑब्जेक्ट पर .c_str() के वापसी मूल्य को अमान्य कर देगा, सबकुछ बस मुश्किल से काम करता है। मुझे लगता है।

+0

जैसा कि dribeas ने बताया, मैं 'std :: pair *' रख सकता हूं और दोनों तक पहुंच प्राप्त कर सकता हूं। अन्यथा, जैसे कि dribeas समझाया गया है, कुंजी में एक निश्चित स्मृति स्थान है, इसलिए सामग्री उस कुंजी पर एक सूचक को स्टोर कर सकती है। मुझे लगता है कि बहुत कम पागल होगा। –

+0

मुझे नहीं लगता कि आप इसे 'टी' में स्टोर कर सकते हैं, क्योंकि 'टी' घोषणा के बिंदु पर अधूरा होगा, और 'जोड़ी' को इसे पूरा करने की आवश्यकता है। कोई इंतजार नहीं है, क्योंकि 'जोड़ी' के लिए पॉइंटर को इसकी आवश्यकता नहीं हो सकती है .... मुझे यकीन नहीं है कि यह काम करता है या नहीं। ये हो सकता है। –

+0

मैं निश्चित रूप से 'टी' में' const std :: string * 'रख सकता हूं। मैं 'value_type *' या iterator को किसी अन्य तत्व के अंदर रखने के बारे में आपका बिंदु देखता हूं, लेकिन मुझे वहां पूरा होने के लिए 'std :: pair' की आवश्यकता नहीं है, क्योंकि मैं सिर्फ एक पॉइंटर संग्रहीत कर रहा हूं। –

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