从std :: map中删除前N个项目?

时间:2016-12-22 13:52:59

标签: c++ c++11 stdmap

尝试编写一个从std :: map中删除第一个(最低键)N项的方法。试过这个:

void EraseNMapElements(const int numElementsToRemove){

    const int originalSize = _map.size();     
    auto eraseIter = _map.begin();
    std::advance(eraseIter, numElementsToRemove);

    _map.erase(_map.begin(), eraseIter);

    assert(_map.size() == (originalSize - numElementsToRemove)) || (0 == originalSize) || (0 == _map.size()));
}

当元素数量超过请求删除的数量时,它可以工作。因此,如果我有五个元素,请求删除2,最后3个元素仍然存在。但是,如果我有一个元素并请求擦除2,我仍然有一个元素。

有没有巧妙的方法来解决这个问题?我可以围绕检查numElementsToRemove大于map.size()来推送IF语句,但必须有更好的解决方案吗?

4 个答案:

答案 0 :(得分:4)

std::advance(i, n)的前提条件是i可以增加至少n次。在您的代码中,您没有检查该前置条件,因此如果您使用numElementsToRemove > originalSize调用它,则会违反该前提条件,从而遇到未定义的行为。要解决此问题,您必须在调用std::advance之前进行检查,可能使用std::min

auto realNumToRemove = std::min(numElementsToRemove, originalSize);
std::advance(eraseIter, realNumToRemove);

答案 1 :(得分:4)

if语句提供了一个简单易读的解决方案:

if (originalSize <= numElementsToRemove) {
    auto eraseIter = _map.begin();
    std::advance(eraseIter, numElementsToRemove);

    _map.erase(_map.begin(), eraseIter);
} else {
    _map.clear(); // or whatever's appropriate
}

答案 2 :(得分:3)

有一件事尚未被提及,而且值得一提的是,因为C ++ 11 std :: map :: erase(const_iterator)实际上将迭代器返回到以下元素。所以代码也可以写成:

function woo_override_checkout_fields( $fields ) {

    $fields['shipping']['shipping_country'] = array(
        'type'      => 'select',
        'required'=>true,
        'label'     => __('Country', 'shop'),
        'options'   => getAllowedCountries()
    );



    $fields['billing']['billing_country'] = array(
        'type'      => 'select',
        'required'=>true,
        'label'     => __('Country', 'shop'),
        'options'   => getAllowedCountries()
    );

    return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'woo_override_checkout_fields' );

这将遍历元素以擦除一次而不是两次。

答案 3 :(得分:1)

我能看到的最简单的方法是使用std::next和if语句。

void EraseNMapElements(const int numElementsToRemove)
{
    if (_map.size() < numElementsToRemove)
        _map.erase(_map.begin(), std::next(_map.begin(), numElementsToRemove));
    else
        _map.clear();
}

请注意_map.size() < numElementsToRemove有符号/无符号不匹配。 numElementsToRemove最好是std::size_tdecltype(_map)::size_type