简化/Neatify这两种方法的循环?
题
我有我的电线交叉的地方(或者我没有足够的睡眠).我需要一个双向的循环,并且我目前代码只是普通的丑陋。
问题:我正在沿着线性datastructre使用索引。我有一个起始指数,可以说,120人。我要运行的交流为双向的。
例如:120,121,119,122,118,123,117,...
我有一个停止标准需要满足的每个方向分开。如果这是满足一个方向,我只是想来碰到的另一个方向,如果两个都得到满足,我需要退出的循环。此外,我需要停止,如果下一个指数是无效的(端的数据结构,说比0或大于200).
例如:停止执行在116倒退和130:120,121,119,122,118,123,117,124,116,(break),125,126,127,128,129,130.
跑进一个方向的第一,那么另一个不幸的是不是一个选项。
我目前代码是普通的丑陋.这是一个很大的纹没有包含任何"生产"的代码。只迭代的逻辑:
int start_idx = 120;
int forward_idx = start_idx;
int backward_idx = start_idx;
bool next_step_forward = true; //should next step be forward or backward?
int cur_idx;
while(backward_idx >= 0 || forward_idx >= 0)
{
if(next_step_forward //if we should step forward
&& forward_idx >= 0) //and we still can step forward
{
cur_idx = ++forward_idx;
if(forward_idx >= 200) //200 is fictive "max index"
{
next_step_forward = false;
forward_idx = -1; //end of data reached, no more stepping forward
continue;
}
if(backward_idx >= 0)
{
next_step_forward = false;
}
}
else if(!next_step_forward
&& backward_idx >= 0)
{
cur_idx = --backward_idx;
if(backward_idx < 0) //beginning of data reached, no more stepping backward
{
next_step_forward = true;
continue;
}
if(forward_idx >= 0)
{
next_step_forward = true;
}
}
else
{
next_step_forward = !next_step_forward; //ever hit?, just security case
continue;
}
//loop body
//do something with cur_idx here
if(stoppingCriterionMet())
{
if(cur_idx > start_idx)
{ //this was a forward step, stop forward stepping
forward_idx = -1;
}
else
{ //this was backward step, stop backward stepping
backward_idx = -1;
}
}
}
我错过了什么?任何提示赞赏。谢谢。
编辑1:有很多非常好的答案,其中把"做一些与cur_idx"成一个单独的功能。虽然这是一个完美的想法我的问题,我更喜欢把迭代码在其他地方,离开的富有成效的代码。我有一个很长的算法和想要分裂它,之后它完成,以尽量减少rearangement的工作。
解决方案
这么发生了,我编写这个问题几乎今天。和我使用了C#迭代的功能做到这一点。但我认为你想要一个更通用的解决方案。
如果您使用的语言,你可以建立自己的迭代(C++、Java,C#),这很容易。你只要做一个自定义迭代,最初吐出数从开始的中心。然后你给迭代的一个额外的功能告诉它停止运行在目前的方向。
如果你正在做这样的事情在C(它看起来C我),可以模仿这一结构包含的迭代态和功能,你的呼叫要步骤,它进或阻止它。
其他提示
这个怎么样?
void do_loop(SomeType *arr, int start, int low, int high, int arr_max)
{
int downwardIndex, upwardIndex;
downwardIndex = upwardIndex = start;
while (downwardIndex > 0 && upwardIndex < arr_max) {
if (downwardIndex < low && upwardIndex > high) {
break;
}
if (downwardIndex > low) {
processElement(arr[downwardIndex]);
downwardIndex--;
}
if (upwardIndex < high) {
processElement(arr[upwardIndex]);
upwardIndex++;
}
}
}
第一次通过在黑客这一(假定C-适应所需的其他语言,但这些概念基本上是中性语言):
void pass1(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
while (lo_x >= lo_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
}
while (hi_x <= hi_limit)
{
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
}
还不清楚会发生什么情况如果启动位置相匹配的停止的标准。应该搜索完全停止,或它应该继续向上或向下的,或这两种方法。我选择了'完全停止'的,但一种情况下可能作出的任何选项列出。在这种情况下的"双方",你甚至不会打扰到停止运行标准检查。
我也选择了去做下之前的上方向;这显然是平凡逆转。订单的最后两个循环并不重要,因为如果两个方向的终止在同一次迭代,既没有后环执行;如果只有一个方向是终止,相对应的循环不会执行,在所有-只有其他会的。
因为那里仍然重复代码中有:
void pass2(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process_lo(&lo_x, lo_limit);
Process_hi(&hi_x, hi_limit);
}
while (lo_x >= lo_limit)
Process_lo(&lo_x, lo_limit);
while (hi_x <= hi_limit)
Process_hi(&hi_x, hi_limit);
}
void Process_lo(int *lo_x, int lo_limit)
{
Process(*lo_x);
if (StopCriterion(*lo_x))
*lo_x = lo_limit - 1;
else
*lo_x--;
}
void Process_hi(int *hi_x, int hi_limit)
{
Process(*hi_x);
if (StopCriterion(*hi_x))
*hi_x = hi_limit + 1;
else
*hi_x++;
}
能见度的控制(静态功能)等左出详细的执行情况的语言。
这是我想的办法,它在C#:
const int UPPER_BOUND = 200;
const int LOWER_BOUND = 0;
const int START = 120;
bool foundlower = false, foundupper = false;
int upper, lower;
upper = lower = START;
while (!foundlower || !foundupper) {
if (!foundlower) {
if (--lower <= LOWER_BOUND) foundlower = true;
if (stoppingCriterionMet(lower)) foundlower = true;
}
if (!foundupper) {
if (++upper >= UPPER_BOUND) foundupper = true;
if (stoppingCriterionMet(upper)) foundupper = true;
}
}