[英]Find all matching elements in std::list
我想知道是否有任何內置或完善的方法(即通過 lambda)來遍歷 std::list 的元素並找到所有與給定值匹配的元素? 我知道我可以遍歷所有這些,但我想我會問是否有辦法讓迭代器只遍歷符合給定條件的元素? 我下面的示例只給了我第一個匹配元素的迭代器。
#include <list>
#include <algorithm>
#include <stdio.h>
int main()
{
std::list<int> List;
List.push_back(100);
List.push_back(200);
List.push_back(300);
List.push_back(100);
int findValue = 100;
auto it = std::find_if(List.begin(), List.end(), [findValue](const int value)
{
return (value == findValue);
});
if (it != List.end())
{
for (; it != List.end(); ++it)
{
printf("%d\n", * it);
}
}
return 0;
}
感謝您的任何反饋。
隨着 C++20 的到來,標准庫現在引入了視圖適配器附帶的范圍的概念,並且只是對集合及其轉換的惰性視圖。
這意味着您現在可以擁有一個“迭代器”,它可用於獲取底層容器/集合的過濾和轉換視圖,而無需創建多個迭代器甚至分配內存。
話雖如此,這是一種僅對列表的過濾元素創建視圖的方法:
// List is your std::list
auto matching_100 = List | std::views::filter([](auto &v) {
return v == 100;
});
那有多甜? 所有你需要使用這一切?
#include <ranges>
#include <list>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
std::list<int> List;
List.push_back(100);
List.push_back(200);
List.push_back(300);
List.push_back(100);
int findValue = 100;
std::copy_if(List.begin(), List.end(), std::ostream_iterator<int>(std::cout, "\n"), [&](int v) {
return v == findValue;
});
return 0;
}
如果您不想直接輸出結果並想用匹配項填充另一個容器:
std::vector<int> matches;
std::copy_if(List.begin(), List.end(), std::back_inserter(matches), [&](int v) {
return v == findValue;
});
boost::filter_iterator
允許你只處理滿足謂詞的可迭代元素。 給定一個謂詞Pred
和一個容器Cont
,
auto begin_iter = boost::make_filter_iterator(Pred, std::begin(Cont), std::end(Cont));
auto end_iter = boost::make_filter_iterator(Pred, std::end(Cont), std::end(Cont));
您現在可以將begin_iter
和end_iter
用作容器的開始和結束迭代器,該容器僅包含滿足Pred
的Cont
元素。 另一個額外的好處是你可以將迭代器包裝在boost::iterator_range
,並在需要可迭代對象的地方使用它,比如基於范圍的for
循環,如下所示:
auto range = boost::make_iterator_range(begin_iter, end_iter);
for(auto x : range) do_something(x);
特別是,將Pred
設置為檢查與您的固定值是否相等的函子(可能是 lambda)將為您提供所需的迭代器。
std::find_if
是一個泛化std::find
當你需要一個函數來檢查你想要的元素,而不是一個簡單的測試是否相等。 如果您只想對相等性進行簡單的測試,則不需要通用形式,而 lambda 只會增加復雜性和冗長性。 只需使用std::find(begin, end, findValue)
代替:
std::vector<std::list<int>::const_iterator> matches;
auto i = list.begin(), end = list.end();
while (i != end)
{
i = std::find(i, end, findValue);
if (i != end)
matches.push_back(i++);
}
但是我不會在循環中調用find
,而是手動編寫循環:
std::vector<std::list<int>::const_iterator> matches;
for (auto i = list.begin(), toofar = list.end(); i != toofar; ++i)
if (*i == findValue)
matches.push_back(i);
std::partition
允許您簡單地將與謂詞匹配的所有元素移動到容器的前面(第一個分區)。 返回值是一個迭代器,指向第二個分區的第一個元素(包含不匹配的元素)。 這幾乎就是“過濾”容器所需的全部內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.