что такое икома kotlin для эквивалента этого итератора python

Вопрос в том, как создать в Kotlin питон, такой как итератор.

Рассмотрим этот код python, который разбирает строку в подстроках:

def parse(strng, idx=1): lst = [] for i, c in itermarks(strng, idx): if c == '}': lst.append(strng[idx:i-1]) break elif c == '{': sublst, idx = parse(strng, i+1) lst.append(sublst) else: lst.append(strng[idx:i-1]) idx = i+1 return lst, i >>>res,resl = parse('{ a=50 , b=75 , { e=70, f=80 } }') >>>print(resl) >>>[' a=50', ' b=75', [' e=7', ' f=80'], '', ' f=80'] 

Это пример игры, чтобы проиллюстрировать итератор python:

 def findany(strng, idx, chars): """ to emulate 'findany' in kotlin """ while idx < len(strng) and strng[idx] not in chars: idx += 1 return idx def itermarks(strng, idx=0): while True: idx = findany(strng, idx, ',{}"') if idx >= len(strng): break yield idx, strng[idx] if strng[idx] == '}': break idx += 1 

У Котлина есть итераторы и генераторы, и, насколько я понимаю, может быть только один тип. Моя идея – определить тип с генератором и экземпляром такого типа. Таким образом, цикл for из «parse» (выше) будет выглядеть так:

для ((i, c) в IterMarks (strng) {……}

Но как я могу определить генератор, и какова лучшая идиома.

Kotlin использует два интерфейса: Iterable<T> (от JDK) и Sequence<T> . Они идентичны, за исключением того, что первый из них нетерпелив, а второй – по ленивому.

Чтобы работать с итераторами или последовательностями, все, что вам нужно сделать, это реализовать один из этих интерфейсов. У Kotlin stdlib есть куча вспомогательных функций, которые могут помочь.

В частности, в 1.1 была добавлена ​​пара функций для создания последовательностей с yield . Они и некоторые другие функции называются generators . Используйте их, если они вам нравятся, или реализуйте интерфейсы вручную.

Хорошо, после некоторой работы, вот Kotlin для итератора:

 import kotlin.coroutines.experimental.* fun iterMarks(strng: String, idx:Int=0)=buildSequence{ val specials = listOf("\"", "{", "}", ",") var found:Pair<Int,String>? var index = idx while (true){ found = strng.findAnyOf(specials, index) if (found == null) break yield (found) index= found.first + 1 } } 

Основными открытиями были то, что итератор может быть возвращен любой функцией, поэтому нет необходимости добавлять методы итератора к существующему объекту. Jetcrains doco прочен, но не хватает примеров, поэтому, надеюсь, приведенный выше пример помогает. Вы также можете работать с основами, и снова заметки хороши, но не хватает примеров. Если есть интерес, я расскажу больше о других подходах.

Затем этот код для «parse» работает:

 fun parse(strng:String, idxIn:Int=1): Pair<Any,Int> { var lst:MutableList<Any> = mutableListOf() var idx = idxIn loop@ for (mark in iterMarks(strng, idx)){ if(mark==null ||mark.first <= idx){ // nothing needed } else { when( mark.second ) { "}" -> { lst.add(strng.slice(idx..mark.first - 1)) idx = mark.first + 1 break@loop } "{" -> { val res: Pair<Any, Int> res = parse(strng, mark.first + 1) lst.add(res.first) idx = res.second } "," -> { lst.add(strng.slice(idx..mark.first - 1)) idx = mark.first + 1 } } } } return Pair(lst, idx) } 

Надеемся, что этот пример сделает его менее полезным для следующего человека, нового для Kotlin, предоставив пример реализации итератора. В частности, если вы знаете, как сделать итератор в python, тогда этот пример должен быть полезен