簡體   English   中英

使用STL映射查找對中第一個元素的最低密鑰對

[英]Find the lowest key pair for the first element in the pair using STL Map

我有一個地圖,其鍵是一對std::map<std::pair<int, int>, struct A> myMap 如何找到和訪問該對中每個唯一的第一個元素的最低對? 例如,

struct A a;
myMap.insert(std::make_pair(std::pair<int, int>(1, 200), a));
myMap.insert(std::make_pair(std::pair<int, int>(1, 202), a));
myMap.insert(std::make_pair(std::pair<int, int>(2, 198), a));
myMap.insert(std::make_pair(std::pair<int, int>(2, 207), a));

我想使用的鍵是<1,200>和<2,198>。 我不需要它們一起返回,我只需要對每個對象進行操作。

謝謝你的時間!

我將尋求最直接的解決方案:

auto previous_first = 0;
auto is_first_iteration = true;
for (const auto& key_value : myMap) {
  const auto& key = key_value.first;
  const auto& value = key_value.second;
  if (is_first_iteration || key.first != previous_first) {
    is_first_iteration = false;
    previous_first = key.first;
    // do something here!
  }
}

在這里,您只需要簡單地遍歷每個元素(並且我們依賴於std :: map的屬性來對元素進行排序。對本身按照第一個然后第二個元素進行排序)。 在每個步驟中,我們都會記住先前的第一個元素-如果在此步驟中相同,則只需跳過此步驟。

@AndrewDurward指出此問題可以在對數時間內解決。 這僅部分正確。 首先,只有在最佳情況下,這個問題才能在對數時間內解決。 如果您有N個元素並且每個元素都有不同的first怎么辦? 您的答案中有N個元素,顯然,您不能在對數時間內輸出N個元素。

您可以使用自定義比較器

struct comp {
bool operator()(const std::pair<int, int>&x, const std::pair<int, int>& y ) const
{
    return x.second < y.second;
}
};

std::map<std::pair<int, int>, struct A,comp > myMap;

然后查找,然后將find_if與pair的第一個元素一起使用。

在您的情況下,默認情況下按std::less<T>進行排序。

因此,以下操作無需定制比較器即可工作,即

std::map<std::pair<int, int>, struct A > myMap;

int search_id=1; //First Element of pair, you can use entire pair too, 
//but that will defeat the purpose of "lowest pair"
auto it=std::find_if(myMap.begin() , myMap.end() , 
                [search_id](const std::pair<std::pair<int, int>, A>& x)
                { return x.first.first == search_id; } 
                );

if(it != myMap.end())
{
std::cout<<it->first.first<<" "<<it->first.second;
}

編輯 :您可以將其用作循環所有元素的功能

有了一個微小的重載助手,您就可以使用std::lower_bound在Coliru上直播

列出的第一個匹配項將是您要查找的匹配項( std::pair<>已按(first,right)升序排列)。

在這種情況下,助手是:

struct ByKeyFirst final { int value; };
inline bool operator<(Map::value_type const& v, ByKeyFirst target) { 
    return v.first.first < target.value; 
}

如您所見,唯一的“增加的復雜性”是檢查是否完全找到了匹配項,但效率應該很好。 您總是可以將復雜性隱藏在(可單元測試的)幫助器中:

Map::const_iterator byKeyFirst(Map const& map, int target)
{
    auto const e = end(map);
    auto lbound = lower_bound(begin(map), e, ByKeyFirst { target });
    if (lbound != e && lbound->first.first == target)
        return lbound;
    return e;
}

現在查找代碼變成:

int main()
{
    const Map myMap { 
        { { 1, 200 }, {} },
        { { 1, 202 }, {} },
        { { 2, 198 }, {} },
        { { 2, 207 }, {} },
    };

    auto match = byKeyFirst(myMap, 2);

    if (end(myMap) != match)
        std::cout << "Matching key: (" << match->first.first << "," << match->first.second << ")\n";
}

完整演示

#include <map>
#include <tuple>
#include <limits>

using namespace std;

struct A {};

using Pair = pair<int,int>;
using Map  = map<Pair, A>;

namespace /*anon*/
{
    struct ByKeyFirst final { int value; };
    inline bool operator<(Map::value_type const& v, ByKeyFirst target) { return v.first.first < target.value; }

    Map::const_iterator byKeyFirst(Map const& map, int target)
    {
        // you can just find the first match, Pair is already sorted by `first`, then `second`:
        auto const e = end(map);
        auto lbound = lower_bound(begin(map), e, ByKeyFirst { target });
        if (lbound != e && lbound->first.first == target)
            return lbound;
        return e;
    }
}

#include <iostream>

int main()
{
    const Map myMap { 
        { { 1, 200 }, {} },
        { { 1, 202 }, {} },
        { { 2, 198 }, {} },
        { { 2, 207 }, {} },
    };

    auto match = byKeyFirst(myMap, 2);

    if (end(myMap) != match)
        std::cout << "Matching key: (" << match->first.first << "," << match->first.second << ")\n";
}

由於map鍵是按字典順序排序的,因此也可以將其視為按其第一個元素排序(盡管有一些重復項)。 這意味着只要我們提供適當的謂詞,我們就可以利用在排序范圍上運行的任何標准算法。 在這種情況下,可以將比較鍵的第一個元素的謂詞編寫為:

    typedef std::map<std::pair<int, int>, struct A> myMap_t;

    auto compare_first = [](
        myMap_t::value_type const & p1,
        myMap_t::value_type const & p2 )
    {
        return p1.first.first < p2.first.first;
    };

完成此操作后,我們只需要選擇正確的算法即可迭代所需的地圖元素。 我們想要映射中的第一個元素,然后是與謂詞所定義的那個不“等效”的第一個元素。 這正是std::upper_bound所做的。

auto e1 = myMap.begin();
auto e2 = std::upper_bound( e1, myMap.end(), *e1, compare_first );

或者我們可以遍歷它們:

for( auto it = myMap.begin(); it != myMap.end(); it = std::upper_bound( it, myMap.end(), *it, compare_first ) )
        std::cout << it->first.first << " " << it->first.second << "\n";

完整的代碼在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM