1
votes

Analyser CSV vers la liste Kotlin

Je suis un peu confus. J'ai cette ligne csv avec des guillemets doubles ("") sous forme de chaînes groupées, et je souhaite la convertir en liste Kotlin. Cependant, il produit un seul tableau de taille 1. Je veux pouvoir obtenir le groupe, suppose à la position 2.

java.lang.IndexOutOfBoundsException: Index: 2, Size: 1

Cela me donne une erreur

val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
var list: List<String> = s.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)")
Log.d("size:", list.size.toString() + " - subjects:" + list[2])


3 commentaires

Quel est votre résultat attendu?


"Sujet 1, Sujet 2, Sujet 3"


Le délimiteur " n'est-il pas dans ce cas?


4 Réponses :


1
votes

Divisez par " et vous obtenez une liste avec size = 3
et ce dont vous avez besoin est à index = 1 .
Ensuite, vous devez diviser l'élément index = 0 par , pour le nom et le numéro:

name: John Doe
number: 13
subjects:Subject 1, Subject 2, Subject 3

Une autre façon si vous ne le faites pas ' t vraiment besoin de la liste mais seulement des valeurs:

val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
val subjects = s.substringAfter("\"").substringBefore("\"").trim()
val name = s.substringBefore(",").trim()
val number = s.substringAfter(",").substringBefore(",").trim()

println("name: " + name)
println("number: " + number)
println("subjects: " + subjects)

imprimera:

val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
val list: List<String> = s.split("\"")
val listStart = list[0].split(",")
val subjects = list[1].trim()
val name = listStart[0].trim()
val number = listStart[1].trim()


4 commentaires

Cela ne fonctionne que si les champs ne contiennent pas le séparateur


Quel séparateur?


merci forpas, comment obtenir John Doe à 0, 13 à 1 et les sujets à 2? Je suppose que le champ est séparé par une virgule.


Votre solution a fonctionné. Mais existe-t-il une autre solution qui utilise la virgule comme séparateur et considère les guillemets doubles comme une valeur groupée?



1
votes

Est-ce utile? Pas beaucoup de test puisque je ne fais aucune affirmation réelle, mais peut-être assez pour vous mettre sur l'idée.

@Test
fun should_make_list_from_quoted_string_in_third_column() {
    val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
    val outerList = s.split(regex = Pattern.compile(","), limit = 3)
    outerList[2].replace("\"","").split(",").forEach( System.out::println )
}

résultat:

John Doe
 13
 "Subject 1, Subject 2, Subject 3"

EDIT 1:

De même ...

@Test
fun should_tolerate_quoted_commas_in_third_column() {
    val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
    val pattern = Pattern.compile(",")
    s.split(regex=pattern, limit=3).forEach( System.out::println )
}


0 commentaires

2
votes

Le regex donné fonctionne très bien. Actuellement, vous essayez de diviser la chaîne s au niveau de l'expression rationnelle brute comme délimiteur, ce qui n'existe pas dans les s . Ajoutez simplement .toRegex () code > à l'expression régulière.

val s = "John Doe, 13, \"Subject 1, Subject 2, Subject 3\""
var list: List<String> = s.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)".toRegex())
Log.d("size:", list.size.toString() + " - subjects:" + list[2])


0 commentaires

2
votes

Je recommande de ne pas faire l'analyse vous-même, mais d'utiliser une bibliothèque existante. (Par exemple, j'ai trouvé Apache Commons CSV facile à utiliser depuis Kotlin.) < / p>

Bien qu'écrire du code d'analyse puisse être amusant et que CSV semble assez simple, il comporte suffisamment de complications et de variations pour que, à moins que vous ne le créiez vous-même, vous risquez de manquer certains cas. (Pas seulement des guillemets échappés, mais d'autres caractères échappés, des guillemets imbriqués, des champs qui incluent des retours à la ligne, des lignes de commentaire ... Et mon piège préféré: MS Excel utilise le séparateur de liste de la machine, qui peut être un point-virgule ou un autre caractère au lieu d'une virgule pour séparer les champs!)

Faites-moi confiance, j'y suis allé…


1 commentaires

ce csv est créé par moi à partir d'une autre application. :-) Btw, je vais jeter un oeil sur votre suggestion pour une future mise à jour.