I´m trying to convert this Kotlin string below to map for removing duplicates names and also remove all the email entry.
var str: String = "name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
My code generates a error:
val array = log_dump.split(";")
var map = emptyMap<String, String>()
for (a in array) {
map = a.split(",").associate {
val (left, right) = it.split("=")
left to right.toString()
}
}
println(map)
CodePudding user response:
here is how you can do it, first change the log_dump to str, since you want to split that, and second thing, you have to remove the last ";" since you don't need that, for me I just check if it is the null or empty string then continue meaning skip this.
fun main() {
var str: String = "name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val array = str.split(";")
var map = emptyMap<String, String>()
for (a in array) {
if(a == ""){
continue
}
map = a.split(",").associate {
val (left, right) = it.split("=")
left to right.toString()
}
}
println(map)
}
Here is how you get all users.
fun main() {
var str: String = "name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val array = str.split(";")
var map = emptyMap<String, String>()
var allUsers = mutableMapOf<Int, MutableList<Pair<String, String>>>()
var count: Int = 0;
for (a in array) {
count = 1
if(a == ""){
continue
}
map = a.split(",").associate {
val (left, right) = it.split("=")
allUsers.getOrPut(count) { mutableListOf() }.add(Pair(left.toString(), right.toString() ))
left to right.toString()
}
}
println(allUsers)
// get the first user info
println(allUsers[1])
}
I am using an online compiler here so let me know if anything goes wrong.
// Output: { name=Hannah Smith, username=hsmith, id=3223423, [email protected]}
CodePudding user response:
The uniqueness constraint is not well defined, do you want to keep the first, last something else? Apart from uniqueness though here is a solution (online demo here) :
data class User(val name: String, val userName: String, val email: String, val id: String)
fun String.cleanSplit(token: String) = this.split(token).map { it.trim() }.filter { it.isNotEmpty() }
fun String.asUserRows() = cleanSplit(";")
fun String.asUser(): User = let {
val attributeMap = this.cleanSplit(",").map { it.cleanSplit("=") }.associate { it[0] to it[1] }
User(attributeMap["name"]!!, attributeMap["username"]!!, attributeMap["email"]!!, attributeMap["id"]!!)
}
fun main() {
val str: String =
"name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val users: List<User> = str.asUserRows().map { it.asUser() }.also { println(it) }
// at this point you can enforce uniqueness on users
// for example this code will have list of users with unique name keeping the last one
users.associateBy { it.name }.values.also { println(it) }
}
}
CodePudding user response:
As Karsten Gabriel said you got an error is because of empty string and also you are overriding users
I understand your question like you want to remove email fields and make data distinct by user.name.
If you want the end result to be string you can do it without maps
val log_dump: String =
"name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val commaRegex = Regex("\\s*,\\s*")
val semicolonRegex = Regex("\\s*;\\s*")
val sanitizedLogDump = log_dump.split(semicolonRegex).asSequence()
.mapNotNull { userString ->
var name: String? = null
val filteredUserFieldString = userString.split(commaRegex) // split by "," and also omit spaces
.filter { fieldString -> // filter field strings not to include email
val keyVal = fieldString.split("=")
// check if array contains exactly 2 items
if (keyVal.size == 2) {
// look for name
if (keyVal[0] == "name") {
name = keyVal[1]
}
// omit email fields
keyVal[0] != "email" // return@filter
} else {
false // return@filter
}
}
.joinToString(separator = ", ") // join field back to string
// omit fieldString without name and add ; to the end of fieldString
if (name == null) null else Pair(name, "$filteredUserFieldString;") // return@mapNotNull
}
.distinctBy { it.first } // distinct by name
.joinToString(separator = " ") { it.second }
println(sanitizedLogDump)
However, if you still want the end result to be map
val log_dump: String =
"name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val commaRegex = Regex("\\s*,\\s*")
val semicolonRegex = Regex("\\s*;\\s*")
val usersMap = log_dump.split(semicolonRegex).asSequence()
.mapNotNull { userString ->
var name: String? = null
val userFieldsMap = userString.split(commaRegex) // split by "," and also omit spaces
.mapNotNull { fieldString -> // filter field strings not to include email and map it to pairs
val keyVal = fieldString.split("=")
// check if array contains exactly 2 items
if (keyVal.size == 2) {
// look for name
if (keyVal[0] == "name") {
name = keyVal[1]
}
// omit email fields
if (keyVal[0] != "email") keyVal[0] to keyVal[1] else null // return@filter
} else {
null // return@filter
}
}
// omit fieldsMap without name
if (name == null) null else Pair(name, userFieldsMap) // return@mapNotNull
}
.toMap()
CodePudding user response:
There are a few small mistakes in your code:
- You get an error because the split also yields an empty string which has to be filtered out.
- You overwrite your result map on each iteration, instead of saving the complete result.
- You should trim your result keys to remove unwanted leading or trailing spaces (e.g. to obtain
username
instead ofusername
).
var str: String = "name=John Trust, username=john3, [email protected], id=434453; name=Hannah Smith, username=hsmith, [email protected], id=23312; name=Hannah Smith, username=hsmith, id=3223423, [email protected];"
val array = str.split(";").filterNot { it.isEmpty() } // 1. filter out non-empty strings
var map = array.map { // 2. use map instead of a for-loop
it.split(",").associate {
val (left, right) = it.split("=")
left.trim() to right.toString() // 3. trim keys
}
}