多维for循环
Multi dimentionnal for loop
有没有简单的方法来转换这个
for (int i=0; i < 31; i++)
for (int j=0; j < 74; j++)
for (int k=1; k < 12; k++)
for (int l=13; l < 15; l++)
...
更简单一点
mfor (int start[]={0,0,1,13}; int max[]={31,74,12,15}) {
printf("%i %i\n", start[1], start[3]);
}
有没有宏或者插件之类的?
这个循环可以迭代思想张量(如图像)来做张量卷积或池化之类的事情。任意维度(可大于4)
或者如何向 C 添加一些语法。我有 mfor
循环的实现。因为 for
循环实际上是一个 while
循环。
没有简单的方法,但您可以实现类似迭代器的类型,在给定范围 n 上生成笛卡尔积:
enum {
MAX = 8
};
typedef struct Combinator Combinator;
struct Combinator {
size_t index; // running index of generated numbers
size_t n; // number of dimensions
int data[MAX]; // current combination
int start[MAX]; // lower and ...
int end[MAX]; // .. exclusive upper limits
};
/*
* Adds a dimensin with valid range [start, end) to the combinator
*/
void combo_add(Combinator *c, int start, int end)
{
if (c->n < MAX && start < end) {
c->data[c->n] = start;
c->start[c->n] = start;
c->end[c->n] = end;
c->n++;
}
}
/*
* Reset the combinator to the lower limits
*/
void combo_reset(Combinator *c)
{
c->index = 0;
memcpy(c->data, c->start, sizeof(c->start));
}
/*
* Get the next comnination in c->data. Returns 1 if there
* is a next combination, 0 otherwise.
*/
int combo_next(Combinator *c)
{
size_t i = 0;
if (c->index++ == 0) return 1;
do {
c->data[i]++;
if(c->data[i] < c->end[i]) return 1;
c->data[i] = c->start[i];
i++;
} while (i < c->n);
return 0;
}
这实现了一个类似里程表的计数器:它递增第一个计数器。如果它溢出,它会重置它并递增下一个计数器,根据需要移动到下一个计数器。如果最后一个计数器溢出,则停止生成组合。 (第一个组合的索引有点混乱,因此您可以从 while
循环的循环条件控制所有内容。可能有更优雅的方法来解决这个问题。)
像这样使用组合器:
Combinator combo = {0}; // Must initialize with zero
combo_add(&combo, 0, 3);
combo_add(&combo, 10, 12);
combo_add(&combo, 4, 7);
while (combo_next(&combo)) {
printf("%4zu: [%d, %d, %d]\n", combo.index,
combo.data[0], combo.data[1], combo.data[2]);
}
此组合器设计为仅使用一次:创建它,设置范围,然后用尽组合。
如果您 break
退出循环,组合子将保留其状态,以便进一步调用 combo_next
继续您中断的地方。您可以通过调用 combo_reset
重新开始。 (这有点像从文件中读取:通常使用它们的方法是读取所有内容,但您可以rewind
。)
有没有简单的方法来转换这个
for (int i=0; i < 31; i++)
for (int j=0; j < 74; j++)
for (int k=1; k < 12; k++)
for (int l=13; l < 15; l++)
...
更简单一点
mfor (int start[]={0,0,1,13}; int max[]={31,74,12,15}) {
printf("%i %i\n", start[1], start[3]);
}
有没有宏或者插件之类的?
这个循环可以迭代思想张量(如图像)来做张量卷积或池化之类的事情。任意维度(可大于4)
或者如何向 C 添加一些语法。我有 mfor
循环的实现。因为 for
循环实际上是一个 while
循环。
没有简单的方法,但您可以实现类似迭代器的类型,在给定范围 n 上生成笛卡尔积:
enum {
MAX = 8
};
typedef struct Combinator Combinator;
struct Combinator {
size_t index; // running index of generated numbers
size_t n; // number of dimensions
int data[MAX]; // current combination
int start[MAX]; // lower and ...
int end[MAX]; // .. exclusive upper limits
};
/*
* Adds a dimensin with valid range [start, end) to the combinator
*/
void combo_add(Combinator *c, int start, int end)
{
if (c->n < MAX && start < end) {
c->data[c->n] = start;
c->start[c->n] = start;
c->end[c->n] = end;
c->n++;
}
}
/*
* Reset the combinator to the lower limits
*/
void combo_reset(Combinator *c)
{
c->index = 0;
memcpy(c->data, c->start, sizeof(c->start));
}
/*
* Get the next comnination in c->data. Returns 1 if there
* is a next combination, 0 otherwise.
*/
int combo_next(Combinator *c)
{
size_t i = 0;
if (c->index++ == 0) return 1;
do {
c->data[i]++;
if(c->data[i] < c->end[i]) return 1;
c->data[i] = c->start[i];
i++;
} while (i < c->n);
return 0;
}
这实现了一个类似里程表的计数器:它递增第一个计数器。如果它溢出,它会重置它并递增下一个计数器,根据需要移动到下一个计数器。如果最后一个计数器溢出,则停止生成组合。 (第一个组合的索引有点混乱,因此您可以从 while
循环的循环条件控制所有内容。可能有更优雅的方法来解决这个问题。)
像这样使用组合器:
Combinator combo = {0}; // Must initialize with zero
combo_add(&combo, 0, 3);
combo_add(&combo, 10, 12);
combo_add(&combo, 4, 7);
while (combo_next(&combo)) {
printf("%4zu: [%d, %d, %d]\n", combo.index,
combo.data[0], combo.data[1], combo.data[2]);
}
此组合器设计为仅使用一次:创建它,设置范围,然后用尽组合。
如果您 break
退出循环,组合子将保留其状态,以便进一步调用 combo_next
继续您中断的地方。您可以通过调用 combo_reset
重新开始。 (这有点像从文件中读取:通常使用它们的方法是读取所有内容,但您可以rewind
。)