Для цикла должен быть итератор()

#kotlin

Вопрос:

Мне нужна эта услуга, в которой, если человек остается дольше 30 минут, он должен платить дополнительные 10 долларов каждые 15 минут (а также за часть из 15).

До сих пор я проектировал его таким образом:

 var checkInTime: Calendar
val totalTime: Long
        get() = (Calendar.getInstance().timeInMillis - checkInTime.timeInMillis) / MIN_IN_MILISEC

fun getTime(totalTime:Long): Int{
        var finalPrice = 0
        var initialPrice = 20

        if(totalTime<31){

            finalFee = initialPrice
        } else {
            val extraPrice = 10
            
            val extraTime = 15

            finalFee = initialPrice
            for(extraTime in totalTime){
                finalFee  = extraTime

        }
        return finalFee
}
 

Я получаю ошибку «Для цикла должен быть итератор ()», когда я пытаюсь выполнить цикл за общее время, когда оно превышает 30 минут, чтобы я мог добавлять по 10 долларов каждые 15 дополнительных минут. Мне нужна помощь в том, как добавлять в финал каждые дополнительные 15 минут, когда человек остается, так как мой метод не работает.
Спасибо.

Комментарии:

1. extraTime-это просто значение, а не список или что-то, что реализует итератор

2. Для циклов повторяйте повторяющиеся объекты, такие как списки объявлений или массивы. Здесь вы пытаетесь выполнить итерацию totalTime , которая не является итерационной, так как это длинный вал, поэтому он не реализует итератор.

Ответ №1:

Давайте взглянем на вашу getTime функцию:

  • Вы используете Long as totalTime . Вы можете измерить его в минутах, чтобы упростить свои вычисления (так как все значения времени измеряются в минутах). Поскольку Long тип в Котлине хранит целое число до 9 223 372 036 854 775807, и ни одна душа на Земле не будет пользоваться вашим сервисом так долго (это составляет 17 миллиардов тысячелетий), вы можете просто использовать an Int .
  • Вы не объявляете finalFee переменную, поэтому код вызовет ошибку «Неразрешенная ссылка». Поскольку вы не используете finalPrice переменную, я предполагаю, что вы хотели использовать ее вместо этого.
  • Вы пытаетесь выполнить итерацию по числовому значению (в данном случае, totalTime , которое является a Long ). Вы можете выполнить итерацию по каждому элементу a List , но как бы вы выполнили итерацию по каждому элементу целого числа? Я предполагаю, что вы хотите совершить определенное действие totalTime несколько раз. В этом случае вы бы использовали диапазоны.
  • Вы также не используете переменные extraPrice и extraTime .
  • Есть код, который является общим для обоих условий if-else ( finalPrice = initialPrice ), поэтому вы можете извлечь его за пределы оператора if -.

Рефакторинг вашей функции:

 fun getTime(totalTime: Int): Int {
    var finalPrice = 20
    if (totalTime >= 30) {
        (0 until totalTime).forEach {
            finalPrice  = 15
        }   
    }
    return finalPrice
}
 

Он короче, но все равно не делает того, что должен: предположим totalTime , что он равен 45. Человек получил 30 минут стоимостью 20 долларов и должен платить только 10 долларов за каждые 15 минут, поэтому заплатит всего 30 долларов. Ваша функция учитывает, что человеку придется заплатить 15 долларов за каждую минуту, в течение которой он оставался, потому что он использует цикл «для», который идет от 0 до totalTime . Для этого вам нужен цикл подготовки, который начинается с 30 (ограничение по времени) от общего времени ( totalTime каждые 15 минут:

 fun getTime(totalTime: Int): Int {
    var finalPrice = 20
    if (totalTime > 30) {
        (30 until totalTime step 15).forEach {
            finalPrice  = 10
        }
    }
    return finalPrice
}
 

Еще лучше, вам даже не нужен цикл, вы можете просто использовать математику:

 fun getTime(totalTime: Int): Int {
    var finalPrice = 20
    if (totalTime > 30) {
        finalPrice  = ((totalTime - 30) / 15) * 10
        //             ^^^^^^^^^^^^^^^^              Get the exceeding time
        //            ^^^^^^^^^^^^^^^^^^^^^^^        How many 15 minutes are there?
        //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^   Put $10 for every 15 minutes
    }
    return finalPrice
}
 

Последняя часть: в вашем вопросе говорилось, что вам также нужно учитывать долю 15. Поэтому вам нужно использовать реальное значение, а не целое число. Давайте изменим его на Double :

 fun getTime(totalTime: Int): Double {
    var finalPrice = 20.0
    if (totalTime > 30) {
        finalPrice  = ((totalTime - 30) / 15.0) * 10
    }
    return finalPrice
}
 

Давайте протестируем вашу функцию:

 fun main() {
    println(getTime(0))    // Outputs 20.0
    println(getTime(10))   // Outputs 20.0
    println(getTime(30))   // Outputs 20.0
    println(getTime(45))   // Outputs 30.0
    println(getTime(60))   // Outputs 40.0
    println(getTime(70))   // Outputs 46.666...
}