for_each给出两个(或 n)个相邻元素
for_each that gives two (or n) adjacent elements
是否有一个标准实现的for_each
调用元素和范围内的下一个元素?
例如,以范围{0, 1, 2, 3, 4, 5}
为例,我想调用一个函数f
,其中包含每个元素及其后继元素:{f(0, 1), f(1, 2), f(2, 3), f(3, 4), f(4, 5)}
请注意最后一个元素是如何被省略的,因为它没有后继元素。
如果将其推广到 n 个随元素本身一起传递的后续产品,那也很好。
到目前为止,我一直在使用迭代器的手写循环中解决这个问题。但是,我想更多地遵循基于 C++11 范围的 for 或 std::for_each
以避免样板代码。
例子
// today: handwritten loop
for(Range::iterator current = range.begin(); current != range.end(); ++current)
f(*current, *std::next(current));
// near future: wrapped version
for_each_pair(range.begin(), range.end(), f);
// slightly further future: generalized version
for_each_tuple<n>(range.begin(), range.end(), f);
附加问题
函数的名称可以改进。对我来说,for_each_pair
/tuple
听起来应该返回范围大小 n 的所有子集(这本身就是我想解决的另一个问题)。所以我想要一些关于更好名字的建议,例如:
for_each_adjacent<n>
临时解决方案
我已经在CR上发布了我自己的解决方案。我不会在这里重复它,因为这是一个标准解决方案,并且已经有足够的自己滚动答案。
您实际上可以为此滥用std::unique
或std::adjacent_find
:谓词与迭代器范围内的每一对连续对一起调用,只要谓词始终返回 false,它就不会修改任何内容或提前返回。
忽略这个特定的黑客,我会将其实现为迭代器适配器,而不是算法。也就是说,我将实现一个consecutive_tuple_iterator<N>
它将返回 N 个连续项目的所有元组。然后你可以用它来做count_if
和includes
之类的事情,而不仅仅是for_each
。(不过,它不适合大多数修改算法。
最简单的方法是将其编写为通用算法,然后多次应用它。
template< typename FwdIter, typename Func >
Func for_each_pair( FwdIter iterStart, FwdIter iterEnd, Func func )
{
if( iterStart == iterEnd )
return func;
FwdIter iterNext = iterStart;
++iterNext;
for( ; iterNext != iterEnd; ++iterStart, ++iterNext )
{
func( *iterStart, *iterNext );
}
return func;
}
当我被问到为什么它返回func(而不是void)时,这是典型的for_each,因为
- func 可以是对象
- 它是按值传递的。
func 可能会"积累"某种状态,但我们在此算法中所做的副本正在积累它,而不是用户的原始对象。因此,我们将修改后的"func"对象传回它们。
对于 C++ 11 和迭代器的新迭代器辅助函数 std::next 和 std::p rev,标准算法 std::transform 的第二个变体可用于迭代相邻元素。
下面是从列表中生成相邻对列表的示例:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::vector<std::pair<int,int>> num_pairs;
if (!nums.empty()) {
std::transform(
std::begin(nums), std::prev(std::end(nums)),
std::next(std::begin(nums)),
std::back_inserter(num_pairs),
std::make_pair<
decltype(nums)::const_reference,
decltype(nums)::const_reference
>
);
}
不完全是你想要的,但看看cpplinq。
int numbers[] = {0, 1, 2, 3, 4, 5};
auto pairs = cpplinq::from_array(numbers)
>> cpplinq::pairwise()
>> cpplinq::to_vector(); // yields (0,1), (1,2), (2,3), (3,4), (4,5)
for(auto p : pairs)
f(p.first, p.second);
留意C++23 浏览::slide(n)
vector<int> ints = {1, 2, 3, 4};
auto rg2 = ints | views::slide(2);
/*
{{1, 2}, {2, 3}, {3, 4}}
*/
auto rg3 = ints | views::slide(3);
/*
{{1, 2, 3},{2, 3, 4}}
*/
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 查找两个排序向量中共有的元素
- 关于比较两个无序数组并删除 a[] 中可以在 b[] 中找到的元素的问题
- 为什么两个矢量元素的地址有这么大的差距?
- 高级选择排序 - 在一次迭代中搜索两个元素
- 如何使用谷歌测试检查两个枚举类元素的相等性?
- C++函数返回两个 char 数组的相同索引元素
- 我想创建一个嵌套数组,该数组由另一个数组中的所有元素组成,但分为两个
- 如何仅考虑 *指针中的前两个元素
- 为什么具有两个元素的发起器语法将一个元素而不是两个元素放入字符串向量中?
- 我应该如何使用remove_if删除两个数字范围内的元素
- 是否可以交换在 c++ 中作为函数 func(say) 中的参数传递的 const 向量的两个元素,例如:vector<int>func (const vector<int>&
- C++ std::向量插入两个元素替代算法失败
- 删除两个相邻的元素并用矢量中的单个元素替换它们
- 如何比较C 列表中的两个连续元素
- 通过将两个参数包的元素线程化为类型对来解压缩这两个参数包
- 数组中两个元素的最大异或
- 优化两个 std::vector<std::complex> 的元素乘积,使用 <float>fftw_malloc() 分配
- 我无法将二维数组的两个元素的差异分配给C++中其他数组的元素?
- 一个数组可以划分的最大子数组,使得不同子数组中任意两个元素的 GCD 始终为 1?