简体   繁体   English

对称迭代一个数组

[英]Iterating An Array Symmetrically

Wasn't exactly sure how to title this, but I hope it makes sense. 不确定如何标题,但我希望它有意义。 I want to iterate an array forwards and then backwards, x number of times. 我想向前迭代一个数组,然后向后迭代x次。 One option is to double the size of the array and then iterate based on mod length, thus iterating in a circular fashion. 一种选择是使数组的大小加倍,然后基于模长度迭代,从而以循环方式迭代。 Assuming an extremely large sequence, that could consume a lot of unnecessary memory. 假设序列非常大,可能会占用大量不必要的内存。 Another option is this: 另一种选择是:

while(++i <= iterations) {
    for(j = 0; j < arrayLength; j++){
        //do something
    }
    for(j = arrayLength - 1; j >= 0; j--){
        //do something
    }
}

That just feels ugly though - I'm sort of repeating myself, just switching the ++/--. 这只是感觉很难看 - 我有点重复自己,只是改变++ / - 。 I'm looking for an elegant coding approach to this. 我正在寻找一种优雅的编码方法。 The language should be C or C++. 语言应该是C或C ++。 Just to be very clear, I'm looking for a different algorithm. 为了清楚起见,我正在寻找一种不同的算法。 Thanks. 谢谢。

boost::adaptors::reverse could come handy here: boost::adaptors::reverse可以派上用场:

#include <boost/range/adaptors.hpp>

while (i++ < iterations) {
    for (auto i : array) /* do something */ ;
    for (auto i : boost::adaptors::reverse(array)) /* do something */ ;
}

In C++14, we'll also have std::rbegin and std::rend , sou you could write something like: 在C ++ 14中,我们还将有std::rbeginstd::rend ,你可以这样写:

auto rb = std::rbegin(array);
auto re = std::rend(array);
while (rb != re) {
    // do something
    ++rb;
}

That is if you're working with plain arrays. 那就是你正在使用普通数组。 Most of standard containers already come with rbegin() and rend() methods that give you reverse iterators. 大多数标准容器已经附带了rbegin()rend()方法,可以为您提供反向迭代器。

Well, here's a different approach. 嗯,这是一个不同的方法。 Not going to claim it's necessarily better by any particular criteria, though. 但是,根据任何特定标准,不会声称它必然更好。

int dir = 1;
int start = 0, end = arrayLength - 1;

while (++i <= (iterations << 1))
{  int j = start;

   do
   { // something
     j += dir;
   } while (j != end);

   dir = -dir;
   int tmp = start; start = end; end = tmp;
}

I actually think that's a bit convoluted, and a maintenance nightmare waiting to happen, but at least you're not "repeating yourself". 我实际上认为这有点令人费解,维护噩梦等待发生,但至少你不是“重复自己”。 And it might be "elegant" in the "clever" sense... Not so much in the "simple" sense. 它可能在“聪明”的意义上是“优雅的”......在“简单”意义上并非如此。

This gives elegance at the cost of some efficiency: 这样可以提高效率:

while(++i <= iterations) {
    for(j = 0; j < twiceArrayLength; ++j) {
        k = min(j, arrayLengthMinusOne) - max(0, j - arrayLength);
        doSomething(k);
    }
}

Example: When arrayLength is 5 , then j will run from 0 to 9 , and the corresponding value of k will run from 0 up to 4 and then from 4 down to 0 . 示例:当arrayLength5j将从0运行到9 ,并且相应的k值将从04运行,然后从40

EDIT: As per your request, to start at a different point in the array, you can do this: 编辑:根据您的要求,从阵列中的不同点开始,您可以这样做:

while(++i <= iterations) {
    endPoint = startPoint + twiceArrayLength;
    for(j = startPoint; j < endPoint; ++j) {
        jModTwiceArrayLength = j % twiceArrayLength;
        k = min(jModTwiceArrayLength, arrayLengthMinusOne) - max(0, jModTwiceArrayLength - arrayLength);
        doSomething(k);
    }
}

Perhaps slightly nicer? 也许稍好一点?

j = -1;

while(++i <= iterations) {
    while(++j < arrayLength){
        //do something
    }
    while(--j >= 0){
        //do something
    }
}

Alternatively, can you operate on the elements in unison? 或者,您可以同时对元素进行操作吗?

while(++i <= iterations) {
    for(j = 0; j < arrayLength; j++){
        //do something with array[j]
        //do something with array[arrayLength - j - 1]
    }
}
while(++i <= iterations)
{
   for(auto it = array.begin(); it!=array.end(); ++it)
   { //do something }

   for(auto it = array.rbegin(); it!=array.rend(); ++it)
   { //do something }

}

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

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