Комментарии 24
// По возрастанию
foreach (int value in Enumerable.Range(1, 10))
{
...
}
// По обыванию
foreach (int value in Enumerable.Range(1, 10).Reverse())
{
...
}
И для Step, наверное, можно .Where() добавить
Если бы действительно требовалось что-то кроме VBA, то изначально бы подключался Python, JScript и т.п. в 5 строк VBA.
А заменить можно, например, так:
for (i = Lower, j = 0; j <= (Upper - Lower) / Step; i += Step, j++)
Изначально задать начало и коэффициент плюс если конец больше или минус один если меньше, после чего в цикле индекса от нуля до модуля разности начального и конечного значений получать значение как начало плюс индекс умноженный на коэффициент.
for i = Lower to Upper step Step
Она универсальна в том смысле, что может ехать как снизу вверх, так и сверху вниз. Ее можно использовать и если Step>0, и если Step<0.
Но ведь если Step отрицательный, надо и Lower c Upper местами поменять, а не просто задать значение Step. А вы почему-то пытаетесь на других языках привести к форме, когда можно только Step поменять.
For indexB = 20 To 1 Step -3
Для Питона надо ```python
range(b, a, -1)
> Оказывается, цикл с использованием range на Python также не позволяет двигаться от большего значения к меньшему, range(b, a) при b>a задает просто пустой диапазон.
1) В питоне range(start, end, step) прекрасно работает с отрицательным шагом.
2) В бейсике цикл не lower to upper, а тоже start to end. Не вводите себя и других в заблуждение.
3) В бейсике и паскале интервалы закрытые (насколько это возможно), в питоне и всех сях (плюсах, шарпе) — полуоткрытые, но в сях можно сделать и закрытыми.
И это принципиальная разница, идеологическая.
По поводу перекодирования.
Начните с того, что существуют несколько разных сценариев использования цикла. Хоть у них и один синтаксис. Соответственно, и перекодирование будет разным (если вы хотите получить человекочитаемый код).
for i = start to finish
= на питонеrange(start, finish+1)
= на сяхfor(i = start; i <= finish; ++i)
Это обычный перебор индексов.for i = finish to start step -1
= на питонеrange(finish, start-1, -1)
= на сяхfor(i = finish; i >= start; --i)
Это перебор в обратном направлении- Перебор в прямом или обратном направлении в зависимости от флага
- Перебор в прямом направлении с произвольным шагом
- Перебор с произвольным шагом в любом направлении
Наверняка в бейсике эти три последних сценария будут сопровождаться какими-то хитростями по вычислению границ цикла — в том числе, из-за работы с закрытыми интервалами.
При переводе на си или питон можно сверху навертеть переход от закрытого к открытому интервалу, но эти правки просто будут уничтожать друг друга. Почему бы не сократить?
В общем виде, на питоне это всего лишь range(start, finish + step, step)
.
На сях — предлагаю не вертеть арифметические формулы со знаком, а написать БУКВАЛЬНО.
for(
i = start;
(step > 0) ? i <= finish : (step < 0) ? i >= finish : false;
i += step
)
Да, кстати. На сях вас ещё ждут весёлые игры с беззнаковыми целыми. После бейсика это будет больно.
Поэтому не просто перекодируйте вашу программу, а в каждом месте крепко задумывайтесь: что вы тут делаете, и может быть, не надо перетаскивать идиомы бейсика в другой язык со своими идиомами и особенностями.
На питоне, например, вместо игр с индексами рекомендуется перебирать прямо элементы массива. А если индексы тоже нужны, то надо перебирать по пронумерованным элементам
for x in array:
print(x)
for i, x in enumerate(array):
print(i, '=>', x)
# вместо
for i in range(len(array)):
print(i, '=>', array[i])
Очевидно, что автоматически перекодировать бейсик в питон с учётом всего этого — будет сложновато, мягко говоря.
Вот код, который вы ищете, для случая когда Step отрицательный.
for (i = Upper; i >= Lower; i += Step)
Хотя в большинстве случаев Step положительный, и делают вот так.
for (i = Upper; i >= Lower; i -= Step)
public sealed class Loop
{
public static void ForNext(int start, int end, int step, Action<int> action)
{
int ind = start;
while(step > 0 ? ind <= end : ind >= end)
{
action(ind);
ind += step;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("begin up loop");
var s = "=>";
Loop.ForNext(1, 6, 2, (n) => Console.WriteLine(s+n));
Console.WriteLine("begin down loop");
s = "<=";
Loop.ForNext(5, -2, -2, (n) => Console.WriteLine(s+n));
Console.ReadLine();
}
}
Выведет:
begin up loop
=>1
=>3
=>5
begin down loop
<=5
<=3
<=1
<=-1
Трудности перевода