¿Cuál es la expresión kotlin para un equivalente a este iterador python

La pregunta es cómo crear un iterador similar a Python en Kotlin.

Considere este código python que analiza cadenas en subcadenas:

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'] 

Este es un ejemplo de juego solo para ilustrar un iterador de 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 

Kotlin tiene iteradores y generadores, y según tengo entendido, solo puede haber uno por tipo. Mi idea es definir un tipo con un generador y una instancia de ese tipo. Entonces, el bucle for de 'parse' (arriba) se vería así:

para ((i, c) en IterMarks (strng) {……}

Pero, ¿cómo puedo definir el generador y cuál es la mejor expresión idiomática?

    Kotlin usa dos interfaces: Iterable<T> (de JDK) y Sequence<T> . Son idénticos, con la exception de que el primero está ansioso, mientras que el segundo es perezoso por convención.

    Para trabajar con iteradores o secuencias, todo lo que tiene que hacer es implementar una de esas interfaces. Kotlin stdlib tiene un montón de funciones de ayuda que pueden ayudar.

    En particular, se agregaron un par de funciones para crear secuencias con yield en 1.1. Ellos y algunas otras funciones se llaman generators . Úselos si lo desea, o implemente las interfaces manualmente.

    OK, después de un trabajo, aquí está el Kotlin para el iterador:

     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 } } 

    Los principales descubrimientos fueron que un iterador puede ser devuelto por cualquier function, por lo que no es necesario agregar los methods de iteración a un object existente. El doco de JetBrains es sólido, pero le faltan ejemplos, así que espero que el ejemplo anterior ayude. También puede trabajar desde lo básico, y de nuevo las notas son buenas pero carecen de ejemplos. Voy a publicar más sobre otros enfoques si hay interés.

    El código de este 'parse' funciona entonces:

     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) } 

    Esperemos que este ejemplo haga que funcione less para la próxima persona nueva en Kotlin, proporcionando un ejemplo de implementación de un iterador. Específicamente, si sabes cómo hacer un iterador en python, entonces este ejemplo debería ser útil