我有一张充满价值的地图:
std::map<std::tuple<int, int, double>, double> Cache;
当地图的大小大于100时,我想删除/删除关键元组中的值都超过10的地图元素。以下是while
和{if
的处理方法。 {1}}:
if (Cache.size() > 100) {
auto it = Cache.begin();
while (it != Cache.end()) {
auto myCache = it->first;
auto actualX = std::get<0>(myCache);
auto actualY = std::get<1>(myCache);
auto actualZ = std::get<2>(myCache);
if (abs(actualX) > 10 || abs(actualY) > 10) || abs(actualZ) > 10)) {
Cache.erase(it++);
} else {
it++;
}
}
}
如何使用find_if
(或其他函数)和lambda函数实现相同的行为?
在浏览评论部分提供的维基百科链接后,我实现了以下代码,但它给出了编译错误:(
Cache.erase(std::remove_if(Cache.begin(),
Cache.end(),
[=](auto &T) -> bool {
auto myCache = T->first;
auto actualX = std::get<0>(myCache);
auto actualY = std::get<1>(myCache);
return std::abs(actualX) > 10|| std::abs(actualY) > 10 || std::abs(actualZ) > 10;
}),
Cache.end());
以上不能与地图一起使用;(
答案 0 :(得分:1)
您可以将std::find_if
与谓词一起使用:
auto pred = []( const auto &t ) {
return std::abs( std::get<0>( t. ) ) > 10 ||
std::abs( std::get<1>( t ) ) > 10 ||
std::fabs( std::get<2>( t ) ) > 10.0 ); };
for( auto it = Cache.begin(); true; it = Cache.erase( it ) ) {
it = std::find_if( it, Cache.end(), pred );
if( it == Cache.end() ) break;
}
答案 1 :(得分:0)
以下内容应该有效
namespace myUtility {
template< typename C, typename P >
void custom_erase_if( C& items, const P& predicate ) {
for( auto it = items.begin(); it != items.end(); ) {
if( predicate(*it) ) it = items.erase(it);
else ++it;
}
}
}
然后,
myUtility::custom_erase_if( Cache, [](const auto& x) {
auto myCache = x.first;
auto actualX = std::get<0>(myCache);
auto actualY = std::get<1>(myCache);
auto actualZ = std::get<2>(myCache);
return ( std::abs(actualX) > 10 ||
std::abs(actualY) > 10 ||
std::abs(actualZ) > 10) ) ;
} );
答案 2 :(得分:0)
您应该做的是安排地图,以便您想要的元素位于地图的背面。
struct over_10 {
bool operator()( std::tuple<int, int, double> const& t) const {
return
(std::get<0>(t)>10 || std::get<0>(t)<-10) // min int doesn't like abs
&& (std::get<1>(t)>10 || std::get<1>(t)<-10)
&& fabs(std::get<2>(t))>10.0;
}
};
template<class Split>
struct split_order {
template<class Lhs, class Rhs>
bool operator()( Lhs const& lhs, Rhs const& rhs ) const {
auto split = Split{};
return std::tie( split(lhs), lhs ) < std::tie( split(rhs), rhs );
}
};
using split_on_10_order = split_order<over_10>;
它的作用是分割排序,以便通过over_10
测试的所有内容都是最后排序的。在每个“分裂”中,一切都是明智的。
现在:
std::map<std::tuple<int, int, double>, double, split_on_10_order> Cache;
auto it = Cache.lower_bound(
std::make_tuple(
std::numeric_limits<int>::min(),
std::numeric_limits<int>::min(),
std::numeric_limits<double>::min()
)
);
Cache.erase( it, Cache.end() );
并完成。
这需要大约O(lg n)时间来找到分割,然后O(m)删除应该删除的m个元素。
答案 3 :(得分:0)
不幸的是,正如Slava指出的那样,export class Client {
name= '';
familyName = '';
public toString(){
return this.name+ " " + this.familyName;
}
无法与地图一起使用。
我认为你的解决方案(擦除不需要的元素的循环)并不坏,但是如果你想使用算法库,那么我最好的就是使用if ENV['USER'].downcase == 'yourusername'
config.vm.synced_folder "/media/hdd", "/media/hdd", type: "virtualbox"
end
来强>移动要保留在临时地图中的元素,然后交换两张地图。
我的意思是......像
一样std::remove_if
不幸的是,lambda函数的std::copy_if()
参数只能从C ++ 14开始提供,所以如果你需要一个C ++ 11解决方案,而不是 if ( Cache.size() > 100 )
{
std::map<std::tuple<int, int, double>, double> CacheTmp;
std::copy_if(std::make_move_iterator(Cache.begin()),
std::make_move_iterator(Cache.end()),
std::inserter(CacheTmp, CacheTmp.end()),
[] (auto const & p)
{ return (std::abs(std::get<0>(p.first)) <= 10)
&& (std::abs(std::get<1>(p.first)) <= 10)
&& (std::abs(std::get<2>(p.first)) <= 10.0); });
Cache.swap(CacheTmp);
}
,你的lambda应该得到一个{ {1}}