什么是kotlin成语相当于这个python迭代器

时间:2017-05-20 02:12:12

标签: iterator sequence kotlin idioms

问题是,如何在Kotlin中创建类似迭代器的python。

考虑这个将字符串解析为子字符串的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

Kotlin有迭代器和生成器,据我所知,每种类型只能有一个。我的想法是定义一个带有生成器和类型实例的类型。所以来自'parse'(上面)的for循环看起来像这样:

for((i,c)in IterMarks(strng){    ......    }

但是我如何定义生成器,以及最好的习语是什么。

2 个答案:

答案 0 :(得分:0)

Kotlin使用两个接口:Iterable<T>(来自JDK)和Sequence<T>。它们是相同的,除了第一个是急切的,而第二个是按惯例懒惰的。

要使用迭代器或序列,您只需实现其中一个接口即可。 Kotlin stdlib有一堆可能有帮助的辅助函数。

特别是1.1中添加了一些用yield创建序列的函数。它们和其他一些函数称为generators。如果您愿意,可以使用它们,或手动实现接口。

答案 1 :(得分:0)

好的,经过一些工作,这里是迭代器的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
    }
}

主要发现是迭代器可以由任何函数返回,因此不需要将迭代器方法添加到现有对象。 JetBrains doco很稳固,但缺乏示例,所以希望上面的例子有所帮助。你也可以从基础工作,再次说明是好的,但缺乏例子。如果有兴趣,我会更多地介绍其他方法。

“解析”的代码可以起作用:

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中创建一个迭代器,那么这个例子应该是有用的