Kotlin的功能样式主函数参数解析

时间:2018-12-27 14:51:38

标签: kotlin parameter-passing

如果这样写问题解答,请告诉我。另外,我也期待更好的答案。我提供的两种解决方案都不完美。

现在Internet上有一些Kotlin参数解析器,例如GitHub: xenomachina/kotlin-argparserGitHub: Kotlin/kotlinx.cliGitHub: ajalt/clikt。但是我不想在我的(也许)小项目中添加这么大的文件夹。我想要的是一个简单干净的解决方案,例如一个函数,并带有“流利的”流样式实现。相反,这些项目都包含几个文件。

我的想法是,只需将命令行参数解析为Map<String, List<String>>,使用map.containsKey()获取no_argument参数,然后使用map[key]获取{ {1}}参数。

例如,命令行参数列表

required_argument

将被解析为:

-a -b c -d e f g -h --ignore --join k --link m n o -p "q r s"

或者我们说

{-a=[], -b=[c], -d=[e, f, g], -h=[], --ignore=[], --join=[k], --link=[m, n, o], -p=[q r s]}

3 个答案:

答案 0 :(得分:2)

好吧,我的解决方案还涉及不可变性和使用last参数折叠。

fun main(args: Array<String>) {
    val map = args.fold(Pair(emptyMap<String, List<String>>(), "")) { (map, lastKey), elem ->
        if (elem.startsWith("-"))  Pair(map + (elem to emptyList()), elem)
        else Pair(map + (lastKey to map.getOrDefault(lastKey, emptyList()) + elem), lastKey)
    }.first

    println(map)

    val expected = mapOf(
        "-a" to emptyList(),
        "-b" to listOf("c"),
        "-d" to listOf("e", "f", "g"),
        "-h" to emptyList(),
        "--ignore" to emptyList(),
        "--join" to listOf("k"),
        "--link" to listOf("m", "n", "o"),
        "-p" to listOf("q r s"))

    check(map == expected)
}

输出

{-a=[], -b=[c], -d=[e, f, g], -h=[], --ignore=[], --join=[k], --link=[m, n, o], -p=[q r s]}

它也处理第一个参数是参数的情况,您可以在map[""]中访问它们

答案 1 :(得分:0)

这是我的实现方式。

mapOf(
    "-a" to listOf(), // POSIX style, no argument
    "-b" to listOf("c"), // POSIX style, with single argument
    "-d" to listOf("e", "f", "g"), // POSIX style, with multiple argument
    "-h" to listOf(), // POSIX style, no argument
    "--ignore" to listOf(), // GNU style, no argument
    "--join" to listOf("k"), // GNU style, with single argument
    "--link" to listOf("m", "n", "o"), // GNU style, with multiple argument
    "-p" to listOf("q r s") // POSIX style, with single argument containing whitespaces
)

使用fun getopt(args: Array<String>): Map<String, List<String>> = args.fold(mutableListOf()) { acc: MutableList<MutableList<String>>, s: String -> acc.apply { if (s.startsWith('-')) add(mutableListOf(s)) else last().add(s) } }.associate { it[0] to it.drop(1) } 将参数及其相应的参数分组(即,将fold转换为[-p0 arg0 arg1 -p1 arg2]),然后将[[-p0, arg0, arg1], [-p1, arg2]]转换为associate。此功能正在流式传输,但需要2次数据传递。另外,如果某些前导参数不带前一个参数,则会导致异常。

答案 2 :(得分:0)

这是另一种实现方式:

fun getopt(args: Array<String>): Map<String, List<String>>
{
    var last = ""
    return args.fold(mutableMapOf()) {
        acc: MutableMap<String, MutableList<String>>, s: String ->
        acc.apply {
            if (s.startsWith('-'))
            {
                this[s] = mutableListOf()
                last = s
            }
            else this[last]?.add(s)
        }
    }
}

直接构造映射结构,但应保留最后一个参数的引用以添加下一个参数。此功能不是 so 流式传输,而只需要传递1次数据即可。而且,它只是简单地丢弃前导参数而没有前一个参数。