簡體   English   中英

在 std::list 中查找所有匹配元素

[英]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>

試試看


上一個答案

使用copy_if迭代器

#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_iterend_iter用作容器的開始和結束迭代器,該容器僅包含滿足PredCont元素。 另一個額外的好處是你可以將迭代器包裝在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.

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