Парс CSV в список Kotlin - PullRequest
       1

Парс CSV в список Kotlin

0 голосов
/ 01 января 2019

Я немного растерялся.У меня есть строка CSV с двойными кавычками ("") в качестве сгруппированных строк, и я хочу преобразовать в список Kotlin.Однако он производит один массив размером 1. Я хочу иметь возможность получить группу, предполагается в позиции 2.

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])

Это дает мне ошибку

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

Ответы [ 4 ]

0 голосов
/ 02 января 2019

Я бы порекомендовал не выполнять анализ самостоятельно, а использовать существующую библиотеку.(Например, я нашел Apache Commons CSV простым в использовании из Kotlin.)

Хотя написание кода анализа может быть забавным, а CSV кажется достаточно простым, у него достаточно сложностей и вариаций, что еслиВы создали это сами, вы, вероятно, пропустите некоторые случаи.(Не только экранированные кавычки, но и другие экранированные символы, вложенные кавычки, поля, содержащие новые строки, строки комментариев ... И моя любимая ошибка: MS Excel использует разделитель списка машины, который может быть точкой с запятой или другим символом вместо запятой для разделения полей!)

Поверь мне, я был там ...

0 голосов
/ 01 января 2019

Это полезно?Не так уж и сложно, поскольку я не делаю никаких реальных утверждений, но, может быть, этого достаточно, чтобы вы поняли идею.

@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 )
}

output:

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

EDIT 1:

Точно так же ...

@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 )
}
0 голосов
/ 01 января 2019

Данное регулярное выражение просто отлично работает.В настоящее время вы пытаетесь разделить строку s в необработанном регулярном выражении в качестве разделителя, которого нет в s.Просто добавьте .toRegex() к регулярному выражению.

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 голосов
/ 01 января 2019

Разделите на ", и вы получите список с size = 3и что вам нужно на index = 1.Затем вам нужно разделить элемент index = 0 на , для имени и номера:

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()

Другой способ, если вам не нужен список, а только значения:

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)

напечатает:

name: John Doe
number: 13
subjects:Subject 1, Subject 2, Subject 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...