簡體   English   中英

使用STL算法查找集合中的所有匹配項

[英]Using STL algorithm to find all matches in a set

我有一個包含Song對象的集合。 我想搜索所有具有特定標題的歌曲。 我需要使用STL算法。

問題是當它找到第一個出現時便停止搜索。

我試圖通過使用while循環並更改從何處開始搜索來修復它,但是我無法使其正常工作。

原始功能

set<Song> SongLibrary::SearchSong(string title)
{
    set<Song> foundSongs;

    find_if(begin(m_songs), end(m_songs),[&](Song const& p)

        {
            if (p.getTitle() == title)
            {
                foundSongs.insert(p);
            }
            return p.getTitle() == title; });

    return foundSongs;
}

這是我嘗試將其修改為使用while循環

while (startSearch != m_songs.end)
{
    find_if(startSearch, end(m_songs), [&](Song const& p) // wont take start search as a parameter
    {
        if (p.getTitle() == title)
        {
            startSearch == m_songs.Position(); // this Line is wrong
            foundSongs.insert(p);
        }
        return p.getTitle() == title; });
}

嘗試使用Copy_if

copy_if(m_songs.begin(), m_songs.end(), foundSongs, [&](Song const& s), s.getTitle() == title);

不幸的是,在諸如copy_if函數中,不能將std::back_inserter用於不具有push_back函數且std::set不具有此功能的容器,但是您可以通過將其復制到向量中來實現相同目的。

// Suppose i want to copy all occurrences of 1
set<int> v{1, 2, 1, 4,1, 6, 1, 1, 9, 10};
vector<int> newSet;
std::copy_if(v.begin(),v.end(),std::back_inserter(newSet),[](int val) {  return val == 1;});

但是,為什么要使用set 從代碼來看,似乎Songs實例不應該以排序的順序存儲。

除非並且直到您需要按照唯一元素的排序順序存儲Songs ,否則您可以使用“ vector”來實現您要執行的操作

vector<int> v{1, 2, 1, 4,1, 6, 1, 1, 9, 10};
vector<int> newSet;
std::copy_if(v.begin(),v.end(),std::back_inserter(newSet),[](int val) { return val == 1;});

對於這種情況,通常需要使用std::copy_if

set<Song> SongLibrary::SearchSong(string title)
{
    set<Song> foundSongs;

    std::copy_if(begin(m_songs), end(m_songs), 
        std::inserter(foundSongs, end(foundSongs)),
        [&](Song const &s) { return s.getTitle() == title; });

}

[除了無關的:我使用了與問題中相同的簽名,但是至少值得考慮通過const引用而不是通過值傳遞參數。]

如果將歌曲存儲在序列容器中(例如, vectordeque ),則可以使用std::partition代替:

auto pos = std::partition(begin(m_songs), end(m_songs), 
    [&](Song const &s) { return s.getTitle() == title; });

在這種情況下, [m_songs.begin(), pos)是匹配請求的歌曲范圍, [pos, m_songs.end())是不匹配的歌曲。

另請注意, set按排序順序存儲項目。 因此,如果在對集合的成員進行排序時將getTitle()用作鍵(或至少是主鍵),則您可能可以更有效地執行操作-您可以使用集合的equal_range成員來查找所有標題相同的歌曲。 這將為您提供對數復雜度的迭代器到范圍的開始和結束。 然后,您將復制該范圍(具有線性復雜度),因此,如果您關注的范圍僅占整個范圍的一小部分,則可能會顯着提高速度。

暫無
暫無

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

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