2015-10-28 5 views
0

Я заметил, что следующие два случая для цикла работают по-разному, в то время как в большинстве случаев они одинаковы. Я не мог понять шаблон, есть ли у кого-нибудь идеи? Благодаря!Scala: декремент for-loop

случай 1:

for (i <- myList.length - 1 to 0 by -1) { ... } 

случай 2:

for (i <- myList.length - 1 to 0) { ...} 
+0

Можете ли вы быть более конкретным о том, что такое «разные» или «те же "и какие значения' myList' создают эти условия? – dhg

+0

случай 2, кажется, работает отлично для большинства ситуаций. Но я просто столкнулся с сценарием, что myList имеет 10 элементов, и он вообще не прошел цикл for. Но эти 10 элементов myList отлично работают с случаем 1. – Edamame

ответ

0

Ну, они, безусловно, не делать то же самое. n to 0 by -1 означает «начать в n и перейти к 0, считая назад на 1. Итак:

5 to 0 by -1 
// res0: scala.collection.immutable.Range = Range(5, 4, 3, 2, 1, 0) 

n to 0 В то время как средства„начинаются в n и получил 0 считая вперед на 1“Но вы будете. Заметим, что если n > 0, то не будет ничего в этом списке, так как нет никакого способа, чтобы рассчитывать вперед до 0 от чего больше нуля.

5 to 0 
// res1: scala.collection.immutable.Range.Inclusive = Range() 

Единственный способ, которым они дают тот же результат, если n=0 поскольку отсчет от 0 до 0 такое же, вперед и назад:

0 to 0 by -1 // Range(0) 
0 to 0   // Range(0) 

В вашем случае, так как вы начинаете на myList.length - 1, они будут производить тот же результат, когда длина myList равна 1.

Таким образом, первая версия имеет смысл, потому что вы хотите отсчитывать до 0 путем подсчета назад (by -1). И вторая версия не имеет смысла, потому что вы не захотите считать вперед до 0 из длины (что обязательно неотрицательно).

0

Во-первых, нам нужно узнать больше о том, как действуют члены to и by.

to - Нажмите Here для API документации
to является членом значение, которое появляется в таких классах, как межд, двойной и т.д.

scala> 1 to 3 
res35: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3) 

Честно говоря, вы не должны использовать start to end by step и start.to (end, step) также будет работать, если вы более комфортно работаете в этом мире. В принципе, to вернет вам Range.Inclusive объект, если мы говорим о целых входах.


by - Нажмите Here для документации API

Создать новый диапазон с начальным и конечным значениями этого диапазона и новый шаг

scala> Range(1,8) by 3 
res54: scala.collection.immutable.Range = Range(1, 4, 7) 
scala> Range(1,8).by(3) 
res55: scala.collection.immutable.Range = Range(1, 4, 7) 

В конец, позволяет потратить некоторое время на то, что происходит, когда шаг находится в другом направлении от начала и до конца. Как 1 to 3 by -1

Вот исходный код класса Range и это на самом деле довольно просто читать:

def by(step: Int): Range = copy(start, end, step) 

Так by на самом деле вызов функции copy, так что копия?

protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step) 

Так copy буквально воссоздать новый диапазон с различным шагом, то давайте посмотрим на конструктор или самого диапазона.

Читая этот абзац кода

override final val isEmpty = (
     (start > end && step > 0) 
    || (start < end && step < 0) 
    || (start == end && !isInclusive) 
) 

Эти случаи будут вызывать исключение и ваш результат будет пустой диапазон в таких случаях, как 1 to 3 by -1 ..etc.

Извините, длина моего сообщения выходит из-под контроля, так как я также изучаю Scala сейчас.
Почему вы просто не читаете исходный код Range, он написан Мартином Одерским, и это всего лишь 500 строк, включая комментарии :)

Смежные вопросы