簡體   English   中英

是否有類似std :: accumulate的東西在迭代器上運行?

[英]Is there something like std::accumulate that operates on iterators?

我想要的:一個迭代器到另一個迭代器之后的另一個迭代器(讓我們稱之為基礎迭代器),它的詞典大於(>)比該基礎迭代器所指向的元素(也就是說,如果我有一個'a',其余的是[c,d,a,b]我想要b,或者更喜歡b)的迭代器。 我不知道可以使用的<algorithm>函數,所以如果你願意的話我會“手工”。

我怎么我能做到:運行這個lambda,在集合上有一些積累:

[mism.first](it_t acc, it_t el) 
{ 
    if(*el > *mism.first) { 
        return iter_min(acc,el); 
    } 
    return acc; 
}

(iter_min(a,b)是* a <= * b時,mism.first是“base iterator”)。 但是由於累積在值而不是迭代器上工作,我不能。 迭代器有這樣的東西嗎? 如果沒有,你會說我應該寫它(我不認為我會用它來過度訓練)或者我只是以“錯誤”的方式去做(順便說一句,我最終會換掉它)由迭代器指向的元素。我知道這聽起來很可怕很多像next_permutation,但是當我在做什么有很多事情要做的排列,這是不太我想要什么)?

我看到的最簡單的可能性是創建一個可以迭代的范圍,包括來自[base, end)連續迭代器。 使用Boost.Iterators counting_iterator可以實現這一點,但即使沒有增強也應該很容易實現。

你提出的lambda幾乎可以正常工作:

some_iterator base = ..., end = ...;
some_iterator the_next_least_thing =
  std::accumulate(boost::make_counting_iterator(base),
                  boost::make_counting_iterator(end),
                  end,
                  [=](some_iterator acc, some_iterator cur) { 
                     return (*cur > *base && (acc == end || *cur < *acc)) ? cur : acc });

要查找大於基數的第一個元素,可以嘗試將std::find_if與lambda謂詞一起使用,如果指向的當前元素大於基本迭代器指向的元素,則返回true。 由於lambdas遺憾的是不是多態的,你需要使用std::iterator_traits指定類型(這樣它也適用於指針)。

要查找大於基數的最小元素,可以進行線性掃描,重復查找剩余列表中大於基數的第一個元素,然后檢查它是否小於當前最小值。 每次更新最小值時,也會將迭代器增加到當前最小值,這樣您只需在剩余部分中查找下一個候選項。 這使得該算法O(N)的元素數量為N

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

template<typename FwdIt>
FwdIt first_larger(FwdIt first, FwdIt last, FwdIt base)
{
    typedef typename std::iterator_traits<FwdIt>::value_type T;

    return std::find_if(first, last, [=](T const& elem) {
         return elem > *base;
    });
}

template<typename FwdIt>
FwdIt first_larger(FwdIt first, FwdIt last)
{
    return first_larger(first, last, first);
}

template<typename FwdIt>
FwdIt min_larger(FwdIt first, FwdIt last)
{
    typedef typename std::iterator_traits<FwdIt>::value_type T;
    auto min = last;
    auto found = false;

    for(auto it = first; it != last; ++it) {
         auto m = first_larger(it, last, first);         
         if (m == last) break;         
         it = min = m;
         found = true;        
    }
    return found? min : last;
}

int main()
{
    std::array<int,11> arr = {{ 54, 314, 5, 7, 1, -1, 0, 14, 9, 8, 6 }};

    auto b = &arr[3]; 
    auto f = first_larger(b, arr.end());
    auto m = min_larger(b, arr.end());

    std::cout << *b << "\n"; // 7
    if(f != arr.end()) std::cout << *f << "\n"; // 14
    if(m != arr.end()) std::cout << *m << "\n"; // 8 

    return 0;
}

你可以將它概括為一個函數

template<typename FwdIt, typename Pred, typename Cmp>
FwdIt min_element_if(FwdIt first, FwdIt last, Pred pred, Cmp cmp)
{
    // return iterator to smallest element satisfying Predicate
}

以及將Cmp設置為等於operator<等的其他重載。不幸的是,STL不包含更多基本算法的這種組合。 您可以查看Boost.Iterator以使用過濾器適配器

 // equivalent to min_element_if(first, last, pred)
 min_element(boost::make_filter_iterator(first, last, pred),
             boost::make_filter_iterator(last, last, pred));

使用find_if,提供迭代器+ 1作為起點:

bool mycomp (char c1, char c2)
{ return lexicographical_compare(*c1,*c1,*c2,*c2); }    

vector<char>::iterator nextBigger = find_if(it+1,end,mycomp)

改編自std lib的lexicographic_compare例程find_if

暫無
暫無

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

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