简体   繁体   English

C ++ 11 STL独有的功能,但反过来

[英]C++11 STL unique function, but in reverse

Is there a function which operates like std::unique , but that takes a custom comparison predicate, and retains the last element in an equivalent sequence, instead of the first? 是否有一个像std::unique一样运行的函数,但它采用自定义比较谓词,并保留等效序列中的最后一个元素,而不是第一个? The answer is yes if C++14 or C++17 is an option; 如果C ++ 14或C ++ 17是一个选项,答案是肯定的; however I am using C++11. 但是我使用的是C ++ 11。

I am starting with a deque of large heavy objects, sorted by one lightweight field. 我开始使用一个大型重物的副本,按一个轻量级场分类。 Some objects have equal values for the lightweight field, and this is unacceptable. 某些对象具有相同的轻量级字段值,这是不可接受的。 I need to discard all but the last object in any sequence with a matching light field. 我需要丢弃除了匹配光场的任何序列中的最后一个对象以外的所有对象。

At present my code calls equal_range using a custom binary predicate and a helper heavy object, then rewinds the end iterator: 目前我的代码使用自定义二元谓词和帮助器重对象调用equal_range ,然后倒回结束迭代器:

deque<Heavy> heavyDeque(...);

Light helperLight(...);
Heavy helperHeavy(helperLight, );

typedef deque<Heavy>:: iterator HevIt;

pair<HevIt, HevIt> deleteRange = equal_range(
    heavyDeque.begin(), heavyDeque.end(), helperHeavy,
    [](const Heavy & lhs, const Heavy & rhs) {
        return lhs.getLight() < rhs.getLight()})

//I have prior knowledge of at least one match
assert(deleteRange.first != deleteRange.second);
// back up; don't delete the last one
--(deleteRange.second);
heavyDeque.erase(deleteRange.first, deleteRange.second);

I am not too happy with having to pass in helperHeavy , when all I need from inside it is helperLight . 我不太高兴不得不传递helperHeavy ,当我需要的内容是helperLight I would rather my code look like this: 我宁愿我的代码看起来像这样:

pair<HevIt, HevIt> deleteRange = magical_range_search(
    heavyDeque.begin(), heavyDeque.end(),
    [helperLight](const Heavy & heavy) {
        return helperLight == heavy.getLight()})

Note that my imaginary magical function takes a unary predicate, not a binary one. 请注意,我的虚构魔法函数采用一谓词,而不是二元谓词。

something like this, perhaps? 也许是这样的事情?

template<typename BidirectionalIterator, typename UnaryPredicate>
pair<BidirectionalIterator,BidirectionalIterator>
magical_range_search(BidirectionalIterator begin,
                     BidirectionalIterator end, UnaryPredicate p)
{
  return {find_if(begin,end,p),
          find_if(make_reverse_iterator(end),make_reverse_iterator(begin),p)};
}

But, of course, for the whole thing you can just use std::unique with a reverse_iterator , as indicated in the comments: 但是,当然,对于整个事情,您可以使用std::uniquereverse_iterator ,如注释中所示:

heavyContainer.erase(heavyContainer.begin(),
                     unique(make_reverse_iterator(heavyContainer.end()),
                            make_reverse_iterator(heavyContainer.begin()),
                            [](Heavy const&lhs, Heavy const&rhs) {
                                return lhs.getLight() < rhs.getLight();
                            }).base());

Here reverse_iterator<>::base() returns the underlying original iterator of the reverse_iterator returned by unique() . 这里reverse_iterator<>::base()返回unique()返回的reverse_iterator的底层原始迭代器。 As unique() returns the new end of the sequence, the reverse operation returns the new begin of the sequence. unique()返回序列的新结尾时,反向操作返回序列的新开始。 The new range is {new_begin, orignal_end} , and the elements in the range {original_begin, new_begin} must be erase() d. 新范围是{new_begin, orignal_end} ,范围{original_begin, new_begin}的元素必须是erase() d。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM