Soru STL haritasını nasıl değerleyebilirim?


STL harita sıralamalarını değere göre nasıl uygularım?

Örneğin, bir haritanım var m:

map<int, int> m;
m[1] = 10;
m[2] = 5;
m[4] = 6;
m[6] = 1;

Bu haritayı sıralamak istiyorum mdeğeri. Yani, haritayı yazdırırsam sonucu şu şekilde almak isterim:

m[6] = 1
m[2] = 5
m[4] = 6
m[1] = 10

Haritayı bu şekilde nasıl sıralayabilirim? Anahtar ve değerle sıralanmış değerlerle başa çıkabileceğim bir yol var mı?


46
2018-04-23 13:50


Menşei


Bakmak boost::bimap - Alexandre C.


Cevaplar:


İlk haritanın anahtarları ve ilk haritanın anahtarları olarak değerler olarak ikinci bir harita oluşturabilirsiniz.

Bu, yalnızca tüm değerler farklıysa çalışır. Bunu kabul edemezseniz, bir harita yerine bir multimap oluşturmanız gerekir.


26
2018-04-23 13:55



haha, mükemmel bir çözüm olabilir. - Charlie Epps
değilse, bir multimap kullanın. - swegi
tüm değerler benzersiz ise, tamam. Aynı değerde birden çok tuşla nasıl başa çıkılır? Yani bu çözüm iyi değil! - Gisway
Bu bir çözüm bile değil. Ya değerler tamamen aynıysa? Sonra ikinci harita sadece 1 elemente sahip olacak! - derek


Tüm anahtar-değer çiftlerini a. set<pair<K, V> > ilk, nerede set çiftin sadece ikinci değerini karşılaştırır, daha az bir functor ile inşa edilir. Bu şekilde, kodunuz değerleri tamamen farklı olmasa bile çalışır.

Veya anahtar / değer çiftlerini a. vector<pair<K, V> >daha sonra bu vektörü daha sonradan daha az functor ile sıralayın.


59
2018-04-23 13:55



Bir soru, şimdi çift hafıza kullanmıyor musunuz? - atoMerz
@AtoMerZ Bu bir sorunsa, set tutma referanslarını yapabilirsiniz. Zaten referansları veya küçük türleri varsa, o zaman önemli değil. - David Schwartz
Vektör çiftlerini sıralamak için: stackoverflow.com/questions/279854/... - juanmirocks
Haritayı bir vektöre 'dökmek': vector<pair<K,V>> v(m.begin(), m.end());  stackoverflow.com/questions/684475/... - juanmirocks
Ama o zaman bu sette nasıl bir anahtar aranacak? Bu saf soru olabilir, lütfen açıklayın. - Vishal Sahu


STL harita sıralama değerini değere göre nasıl uygulayabilirim?

Yapamazsın tanım olarak. Harita, elemanını anahtar ile sıralayan bir veri yapısıdır.


15
2018-04-23 13:52



Bu işlevi nasıl uygulayabilirim? Bu işleve ihtiyacım var. - Charlie Epps
@Charlie Epps: Başka bir haritayla mı? İlk haritaya bir anahtar / değer eklediğinizde, saniyeye bir değer / anahtar eklersiniz. - paercebal


Kullanmalısın Boost.Bimap bu tür şeyler için.


4
2018-04-23 13:53



... haritanızın bire bir olması sağlandı. - Vlad
Aslında Boost.Bimap, bire-bir olmayan işlemleri desteklemektedir. Örneğin, bimap<multiset_of<int>, set_of<double> > - rlbond


C ++ kitabımda da benzer bir soru yaptım. Geldiğim cevap çok verimli olmayabilir:

int main()
{
    string s;
    map<string, int> counters;

    while(cin >> s)
        ++counters[s];

    //Get the largest and smallest values from map
    int beginPos = smallest_map_value(counters);
    int endPos = largest_map_value(counters);

    //Increment through smallest value to largest values found
    for(int i = beginPos; i <= endPos; ++i)
    {
        //For each increment, go through the map...
        for(map<string, int>::const_iterator it = counters.begin(); it != counters.end(); ++it)
        {
            //...and print out any pairs with matching values
            if(it->second == i)
            {
                cout << it->first << "\t" << it->second << endl;
            }
        }
    }
    return 0;
}

//Find the smallest value for a map<string, int>
int smallest_map_value(const map<string, int>& m)
{
    map<string, int>::const_iterator it = m.begin();
    int lowest = it->second;
    for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
    {
        if(it->second < lowest)
            lowest = it->second;
    }
    return lowest;
}

//Find the largest value for a map<string, int>
int largest_map_value(const map<string, int>& m)
{
    map<string, int>::const_iterator it = m.begin();
    int highest = it->second;
    for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
    {
        if(it->second > highest)
            highest = it->second;
    }
    return highest;
}

1
2017-08-16 02:45





Başka bir harita oluşturun, değer değil anahtarına göre daha az () işlev sağlayın VE değer1 ise işlev true olarak dönmelidir. <= değer2 (kesinlikle <değil). Bu durumda, farklı olmayan değerlere sahip öğeler de sıralanabilir.


0
2018-02-07 03:10





@ Swegi’nin fikrine dayanarak, c ++ 11 kullanarak multimap:

map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
multimap<int, int> mm;

for(auto const &kv : m)
    mm.insert(make_pair(kv.second, kv.first));  // Flip the pairs.

for(auto const &kv : mm)
    cout << "m[" << kv.second << "] = " << kv.first << endl;  // Flip the pairs again.

İdeone Kodu

Ayrıca, bir çiftler vektörünü kullanarak @Chris'in fikrine dayanan bir C ++ 11 çözümü uyguladım. Doğru sıralama için lambda ifadesi karşılaştırmalı olarak

map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
using mypair = pair<int, int>;

vector<mypair> v(begin(m), end(m));

sort(begin(v), end(v), [](const mypair& a, const mypair& b) { return a.second < b.second; });

for(auto const &p : v)
    cout << "m[" << p.first << "] = " << p.second << endl;

İdeone Kodu

İlk çözüm daha kompakttır, ancak her iki çözüm de kabaca aynı performansa sahip olmalıdır. İçine ekleme multimap olduğunu O (log n)ama bunun için yapılması gerekiyor n ile sonuçlanan girişler O (n log n). Vektörün ikinci çözümde sıralanması da sonuçlanır. O (n log n).

Ayrıca, bir çift çifti kullanmak için @Chris 'fikrini denedim. Ancak, değerler tamamen farklı değilse işe yaramaz. Sadece çiftin ikinci elemanını karşılaştıran bir functor kullanmak yardımcı olmaz. İlk eklerseniz make_pair(1, 1) küme içine ve sonra eklemek için deneyin make_pair(2, 1)Daha sonra ikinci çift eklenmeyecektir, çünkü her iki çift de bu set tarafından özdeş olarak görülür. Bu efekti görebilirsiniz burada Ideone'da.


0
2018-02-07 20:42



İkinci çözüm ayrıca, harita değerleri için önemsiz olmayan veri tiplerini sıralamaya genel olarak yarar sağlama avantajına sahiptir. - Jamie Bullock