На этом шаге мы рассмотрим еще несколько функций, поддерживающих итерации.
Цикл for и функция forEach() обрабатывают индексы неявно. Если вам потребуется получить индекс каждого элемента в списке, используйте forEachIndexed(). Измените код Tavern.kt и используйте функцию forEachIndexed(), чтобы вывести место каждого посетителя в очереди.
. . . . fun main() { . . . . placeOrder("shandy,Dragon's Breath,5.91") patronList.forEachIndexed { index, patron -> println("Good evening, $patron - you're #${index + 1} in line.") } } . . . .
Рис.1. Вывод позиции строки в списке с помощью forEachIndexed (Tavern.kt)
Запустите Tavern.kt снова, чтобы увидеть посетителей в очереди:
Good evening, Eli - you're #1 in line. Good evening, Mordoc - you're #2 in line. Good evening, Sophie - you're #3 in line.
Рис.2. Результат работы приложения
Функции forEach() и forEachIndexed() доступны и для некоторых других типов в Kotlin. Эта категория типов называется Iterable (итерируемые) и включает List, Set, Map, IntRange (диапазоны типа 0...9) и другие типы коллекций. Итерируемые типы поддерживают итерацию - другими словами, они позволяют выполнить обход хранимых элементов и выполнить некоторые действия с каждым из них.
Настала пора вернуться к имитации таверны. Теперь каждый посетитель хочет заказать Dragon's Breath. Для этого переместите вызов placeOrder() внутрь лямбды, которая передается в функцию forEachIndexed(), чтобы она вызывалась для каждого посетителя в списке. Теперь, когда заказать напиток могут все посетители, а не только игрок, измените placeOrder(), чтобы она принимала имя посетителя, сделавшего заказ.
Также закомментируйте вызов performPurchase() в placeOrder(). (Он понадобится нам в дальнейшем.)
. . . . fun main() { . . . . patronList.forEachIndexed { index, patron -> println("Good evening, $patron - you're #${index + 1} in line.") placeOrder(patron, "shandy,Dragon's Breath,5.91") } } . . . . private fun placeOrder(patronName: String, menuData: String) { val indexOfApostrophe = TAVERN_NAME.indexOf('\'') val tavernMaster = TAVERN_NAME.substring(0 until indexOfApostrophe) println("$patronName speaks with $tavernMaster about their order.") val (type, name, price) = menuData.split(',') val message = "$patronName buys a $name ($type) for $price." println(message) // performPurchase(price.toDouble()) val phrase = if (name == "Dragon's Breath") { "$patronName exclaims: ${toDragonSpeak("Ah, delicious $name!")}" } else { "$patronName says: Thanks for the $name." } println(phrase) }
Рис.3. Моделирование нескольких заказов (Tavern.kt), функция main()
Рис.4. Моделирование нескольких заказов (Tavern.kt), функция placeOrder()
Запустите Tavern.kt и посмотрите, как таверна оживает с приходом трех посетителей, заказывающих Dragon's Breath:
The tavern master says: Eli's in the back playing cards. The tavern master says: Yea, they're seated by the stew kettle. Good evening, Eli - you're #1 in line. Eli speaks with Taernyl about their order. Eli buys a Dragon's Breath (shandy) for 5.91. Eli exclaims: Ah, d3l1c10|_|s Dr4g0n's Br34th! Good evening, Mordoc - you're #2 in line. Mordoc speaks with Taernyl about their order. Mordoc buys a Dragon's Breath (shandy) for 5.91. Mordoc exclaims: Ah, d3l1c10|_|s Dr4g0n's Br34th! Good evening, Sophie - you're #3 in line. Sophie speaks with Taernyl about their order. Sophie buys a Dragon's Breath (shandy) for 5.91. Sophie exclaims: Ah, d3l1c10|_|s Dr4g0n's Br34th!
Рис.5. Результат работы приложения
Итерируемые коллекции поддерживают разнообразные функции, позволяющие определять действия, которые необходимо выполнить для каждого элемента коллекции. Об Iterable и других функциях итераций подробнее мы поговорим позднее.
На следующем шаге мы рассмотрим чтение файла в список.