如何从数组的字符串中拆分检索数据。
对象具有一系列可以是多维的变量。
演示输入字符串
-3
预期结果
CONTAINER [1, "one", false, [CONTAINER [2, "two", false]], 42, true]
(然后我将参加第5组,然后再次运行它以获取其余的对象)
什么是拆分字符串以获取内部数据的好方法?
可以使用正则表达式吗?
如果其他布局可以简化字符串的设置,我确实可以选择不同的字符串格式。
答案 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)
}
}