2012-03-23 19 views
5

Yani pairs<string ,string>C++ çift eleman için arama ayarlandı mı?

bir dizi var Ve ben ilk ben ikinci dönmek istiyorum, sonra ben bu dizeyi bulursanız "ilk" çiftinin olacağını tek bir dize aramak için find() kullanmak istiyorum Bu fonksiyondan. Benim şu anki girişimdir

..

myList::iterator i; 

i = theList.find(make_pair(realName, "*")); 

return i->second; 
+7

Neden "map" kullanmıyorsunuz? Diğer notlar: eğer bir "std :: set" ise, neden myList' denir? Std :: pair's için bir karşılaştırma işlevi oluşturdunuz mu? Nasıl görünüyor? –

cevap

2

Bunun için std::set<std::pair<std::string, std::string> > kullanabilirsiniz fakat paritenin ilişkisel operatör bunun için iki elemanı alır çünkü bunun için özel bir karşılaştırma nesnesi gerekir. Yani, bunun yerine aslında bir std::map<std::string, std::string> kullanmalısınız gibi görünüyor.

+1

Ben katılmıyorum, semantik oldukça farklı olurdu, özellikle aynı "anahtar" ile birkaç öğe saklamak için yetersizlik. Bir 'multimap' semantik açıdan daha yakın olabilir, ancak daha sonra çiftin arzu edilebilir olması için tekliğini garanti etmez. Gereksinimi bilmeden, cevabınız karanlıkta bir atış ... –

1

std::pair için < tanımı sözlük sözlüğü uygular ve "" dizeleri için en düşük değerdir. Bu birleştirerek elde ederiz: hile uygun lower_bound kullanıyor

typedef std::pair<std::string, std::string> StringPair; 
typedef std::set<StringPair> Set; 

std::string const* find_first(Set const& s, std::string const& key) { 
    Set::const_iterator const it = s.lower_bound(std::make_pair(key, "")); 

    // Check that it actually points to a valid element whose key is of interest. 
    if (it == s.end() or it->first != key) { return 0; } 

    // Yata! 
    return &it->second; 
} 

.

value'dan daha düşük olmayan birinci öğeyi işaret eden bir yineleyici döndürür.

  • o end() dönerse, o zaman ilginç bir şey bulamadık. Bu sadece aralığın ilk elemanını döndürür olsa işaret olur

  • Aksi takdirde it->first >= key yüzden (hiçbir ilgi bize) > durumda kurtulmak. Eğer tüm elemanları ile ilgili, şunları deneyin: Bu ilk elemanı key eşittir s düğüm dizi dönecektir

    typedef std::pair<Set::const_iterator, Set::const_iterator> SetItPair; 
    
    SetItPair equal_range_first(Set const& s, std::string const& key) { 
        StringPair const p = std::make_pair(key, ""); 
        return std::make_pair(s.lower_bound(p), s.upper_bound(p)); 
    } 
    

    . O zaman sadece bu aralığı üzerinde yineleme zorunda:

    for (Set::const_iterator it = range.first; it != range.second; ++it) { 
        // do something 
    } 
    

    Ve hatta lower_bound veya upper_bound dönüş sonuydu olup olmadığını endişelenmenize gerek yok.

    • lower_bound ise döner end(), o zaman upper_bound yapar ve döngü atlanır
    • bir düğüme lower_bound noktaları olan it->first > key, daha sonra upper_bound aynı düğüm işaret edecektir, ve döngü
    • atlanırsa

    Bu, aralıkların gücüdür: özel kontroller yapmaya gerek yoktur, aralıklar eşleşmediğinde boştur, ve böylece bunların üstündeki döngü ... tek bir kontrolde atlanır.

  • +0

    ikinci eleman bir int ise? – user3522401

    6

    C++ 11 kabul edilebilir midir?şöyle diyoruz sonra

    struct MatchFirst 
    { 
         MatchFirst(const string& realName) : realName(realName) {} 
    
         bool operator()(const pair<string, string>& val) { 
           return val.first == realName; 
         } 
    
         const string& realName; 
    }; 
    

    :

    auto it = find_if(theList.begin(), theList.end(), 
        [&](const pair<string, string>& val) -> bool { 
         return val.first == realName; 
        }); 
    
    return it->second; 
    

    Veya C++ 03

    , ilk bir functor tanımlamak

    myList::iterator it = find_if(a.begin(), a.end(), MatchFirst(realName)); 
    return it->second; 
    

    Bu yalnızca ilk maçı dönecek ama gelen senin soru, beklediğiniz her şeye benziyor.