如何分割多维数组字符串

时间:2018-08-09 16:18:25

标签: java arrays regex multidimensional-array kotlin

如何从数组的字符串中拆分检索数据。

对象具有一系列可以是多维的变量。

演示输入字符串

-3

预期结果

CONTAINER [1, "one", false, [CONTAINER [2, "two", false]], 42, true]

(然后我将参加第5组,然后再次运行它以获取其余的对象)

什么是拆分字符串以获取内部数据的好方法?

可以使用正则表达式吗?


如果其他布局可以简化字符串的设置,我确实可以选择不同的字符串格式。

2 个答案:

答案 0 :(得分:1)

最简单的方法,使用split():

val input = """CONTAINER [1, "one", false, [CONTAINER [2, "two", false]], 42, true]"""

input.split(" ", "[", ",", "]").filter {
    it != ""
}.forEach {
    println(it)
}

输出:

CONTAINER
1
"one"
false
CONTAINER
2
"two"
false
42
true

答案 1 :(得分:0)

由于可以手动识别根容器中的数组,因此我可以将方括号替换为常规方括号,从而更轻松地检索数据

input = if(input.endsWith("]]]")) replaceLast(input, "]]]", "])]") else replaceLast(input, "]], ", "]), ")

        val arraySplit = input.split("(", ")")

从那里可以使用正则表达式模式来迭代嵌套,以检索和替换所有后续容器

private val pattern = Pattern.compile("([A-Z]+\\s\\[[^\\[\\]]+])")

不像我想要的那样干净,但是它可以正常工作。主要关心的问题是支持嵌套的多层,例如以下示例:

输入

CONTAINER [1, "one", false, [CONTAINER [2, "two", CONTAINER [3, "three"], CONTAINER [false], true], CONTAINER [2, "string", false], CONTAINER [4]], 42, true]

输出

CONTAINER [1, "one", false, [$array], 42, true]
$array = $4, $2, $3
$0 = CONTAINER [3, "three"]
$1 = CONTAINER [false]
$2 = CONTAINER [2, "string", false]
$3 = CONTAINER [4]
$4 = CONTAINER [2, "two", $0, $1, true]

感谢@Alexey Soshin提供的split()示例。

全班制:

import org.junit.Assert
import org.junit.Test
import java.util.regex.Pattern

class ContainerTest {

    private val pattern = Pattern.compile("([A-Z]+\\s\\[[^\\[\\]]+])")

    /**
     * Checks if string contains a full array in the middle or at the end of the container values
     * @return whether a verified container contains an array
     */
    private fun hasArray(string: String): Boolean {
        return string.contains(", [") && (string.contains("]], ") || string.endsWith("]]]"))
    }

    /**
     * Replaces last occurrence of a substring
     * Credit: https://stackoverflow.com/a/16665524/2871826
     */
    private fun replaceLast(string: String, substring: String, replacement: String): String {
        val index = string.lastIndexOf(substring)
        return if (index == -1) string else string.substring(0, index) + replacement + string.substring(index + substring.length)
    }

    /**
     * Splits root container and returns string contents of it's array
     */
    private fun extractArray(string: String): String {
        if(!hasArray(string))
            return ""

        //Replace square brackets of array with regular so it's easier to differentiate
        var input = string
        input = input.replaceFirst(", [", ", (")
        input = if(input.endsWith("]]]")) replaceLast(input, "]]]", "])]") else replaceLast(input, "]], ", "]), ")

        val arraySplit = input.split("(", ")")
        return arraySplit[1]//Always the second index
    }

    private fun replaceArray(input: String, array: String): String {
        return input.replaceFirst(array, "\$array")
    }

    /**
     * Iterates pattern matching for the remainder containers
     * @return list of individual container strings
     */
    private fun extractContainers(string: String): ArrayList<String> {
        var array = string
        val containers = arrayListOf<String>()
        var index = 0

        //Nature of pattern matches deepest level first then works it's way upwards
        while(array.contains("[")) {//while has more containers
            val matcher = pattern.matcher(array)

            while (matcher.find()) {
                val match = matcher.group()
                containers.add(match)
                array = array.replace(match, "\$${index++}")
            }
        }
        return containers
    }

    /**
     * Replaces container strings with placeholder indices
     */
    private fun replaceContainers(string: String, containers: ArrayList<String>): String {
        var array = string
        containers.forEachIndexed { index, s -> array = array.replaceFirst(s, "\$$index") }
        return array
    }

    /**
     * Splits container variables
     * @return array of values
     */
    private fun getVariables(string: String): List<String> {
        return string.substring(11, string.length - 1).split(", ")
    }

    @Test
    fun all() {
        val input = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\", CONTAINER [3, \"three\"], CONTAINER [false], true], CONTAINER [2, \"string\", false], CONTAINER [4]], 42, true]"//"""CONTAINER [1, "one", false, [CONTAINER [2, "two", false]], 42, true]"""

        if(hasArray(input)) {
            val array = extractArray(input)

            val first = replaceArray(input, array)

            val containers = extractContainers(array)

            val final = replaceContainers(array, containers)

            println("$first ${getVariables(first)}")

            println("\$array = $final")

            containers.forEachIndexed { index, s -> println("\$$index = $s ${getVariables(s)}") }
        }
    }

    private val emptyLast = "CONTAINER [1, \"one\", false, []]"
    private val oneLast = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\"]]]"
    private val twoLast = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]]]"
    private val threeLast = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]]]"

    private val empty = "CONTAINER [1, \"one\", false, [], 42]"
    private val one = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\"]], 42]"
    private val two = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]], 42]"
    private val three = "CONTAINER [1, \"one\", false, [CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]], 42]"

    @Test
    fun hasArray() {
        Assert.assertFalse(hasArray(emptyLast))
        Assert.assertTrue(hasArray(oneLast))
        Assert.assertTrue(hasArray(twoLast))

        Assert.assertFalse(hasArray(empty))
        Assert.assertTrue(hasArray(one))
        Assert.assertTrue(hasArray(two))
    }

    @Test
    fun extractArray() {
        Assert.assertTrue(extractArray(empty).isEmpty())
        Assert.assertTrue(extractArray(emptyLast).isEmpty())

        Assert.assertEquals(extractArray(oneLast), "CONTAINER [2, \"two\"]")
        Assert.assertEquals(extractArray(twoLast), "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]")
        Assert.assertEquals(extractArray(threeLast), "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]")
        Assert.assertEquals(extractArray(one), "CONTAINER [2, \"two\"]")
        Assert.assertEquals(extractArray(two), "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]")
        Assert.assertEquals(extractArray(three), "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]")
    }

    @Test
    fun replaceArray() {
        val last = "CONTAINER [1, \"one\", false, [\$array]]"
        val first = "CONTAINER [1, \"one\", false, [\$array], 42]"
        Assert.assertEquals(replaceArray(oneLast, "CONTAINER [2, \"two\"]"), last)
        Assert.assertEquals(replaceArray(twoLast, "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]"), last)
        Assert.assertEquals(replaceArray(threeLast, "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]"), last)

        Assert.assertEquals(replaceArray(one, "CONTAINER [2, \"two\"]"), first)
        Assert.assertEquals(replaceArray(two, "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]"), first)
        Assert.assertEquals(replaceArray(three, "CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]"), first)
    }

    @Test
    fun extractContainers() {
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\"]").size, 1)
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]").size, 3)
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]").size, 4)
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\"]").size, 1)
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"]").size, 3)
        Assert.assertEquals(extractContainers("CONTAINER [2, \"two\", CONTAINER [3, \"three\"]], CONTAINER [4, \"four\"], CONTAINER [5, \"five\"]").size, 4)
    }
}