Как создать новый список строк из списка длинных в Kotlin? (встроенный, если возможно)

#kotlin

#kotlin

Вопрос:

У меня есть список длин в Kotlin, и я хочу сделать их строками для целей пользовательского интерфейса, возможно, с каким-то префиксом или каким-то образом измененными. Например, добавив «$» в начале или слово «доллары» в конце.

Я знаю, что могу просто перебрать их все, например:

 val myNewStrings = ArrayList<String>()
longValues.forEach { myNewStrings.add("$it dollars") }
  

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

РЕДАКТИРОВАТЬ / ОБНОВИТЬ: Извините за первоначальную путаницу в моих терминах. Я имел в виду написание кода в одну строку, а не встраивание функции. Я знал, что это возможно, но не мог вспомнить map функцию функции kotlin на момент написания. Спасибо всем за полезную информацию. Я многому научился, спасибо.

Комментарии:

1. Почему вы не хотите создавать новый список строк? Вы профилировали свой код и обнаружили, что это узкое место?

2. «Я чувствую, что есть способ встроить это или изменить исходный длинный список без создания нового списка строк?» Это противоречит подходу к функциональному программированию и лучшим практикам даже на нефункциональных языках, таких как Java. Всегда стремитесь сделать вещи неизменяемыми, вот почему это поведение по умолчанию в Kotlin. Трудно рассуждать о переменных, которые постоянно изменяются, тогда как создание нового списка с помощью ваших манипуляций легче рассуждать.

Ответ №1:

Вы ищете карту, карта принимает лямбда-выражение и создает список на основе результата лямбда-выражения

 val myNewStrings = longValues.map { "$it dollars" }
  

map это расширение, которое имеет 2 общих типа, первый предназначен для определения того, какой тип повторяется, а второй — какой тип будет возвращен. Лямбда, которую мы передаем в качестве аргумента, на самом деле transform: (T) -> R , чтобы вы могли видеть, что это должна быть функция, которая получает a T , который является исходным типом, а затем возвращает an R , который является результатом lambda. В Lambdas не нужно указывать return, потому что по умолчанию возвращается последняя строка.

Ответ №2:

Вы можете использовать map -function on List . Он создает новый список, в котором к каждому элементу была применена функция.

Вот так:

 val myNewStrings = longValues.map { "$it dollars" }
  

Ответ №3:

В Kotlin inline есть ключевое слово, которое ссылается на компилятор, заменяющий вызов функции содержимым функции напрямую. Я не думаю, что это то, о чем вы спрашиваете здесь. Возможно, вы имели в виду, что хотите написать код в одной строке.

Возможно, вы захотите ознакомиться с документацией по коллекциям, в частности с разделом сопоставления.

Преобразование сопоставления создает коллекцию из результатов функции для элементов другой коллекции. Основная функция сопоставления map() . Он применяет данную лямбда-функцию к каждому последующему элементу и возвращает список результатов лямбда. Порядок результатов такой же, как и исходный порядок элементов.

 val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
  

Для вашего примера это будет выглядеть так, как говорили другие:

 val myNewStrings = longValues.map { "$it dollars" }
  

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

Нет. У вас есть Long s, и вы хотите String s. Единственный способ — создать новые String s. Вы могли бы избежать создания нового List , изменив тип исходного списка с List<Long> на List<Any> на и отредактировав его на месте, но это было бы излишним и сделало бы код чрезмерно сложным, более сложным для понимания и более подверженным ошибкам.

Ответ №4:

Как уже говорили люди, если здесь нет проблем с производительностью (например, миллиард строк, когда вы используете только несколько), вероятно, нужно просто создать нужный вам список. Однако у вас есть несколько вариантов!

Последовательности вычисляются лениво, при наличии длинной цепочки операций они завершают цепочку для каждого элемента по очереди, вместо создания промежуточного полного списка для каждой операции в цепочке. Так что это может означать меньшее использование памяти и большую эффективность, если вам нужны только определенные элементы или вы хотите остановиться раньше. У них есть накладные расходы, поэтому вы должны быть уверены, что оно того стоит, и для вашего варианта использования (превращение списка в другой список) нет промежуточных списков, которых следует избегать, и я предполагаю, что вы используете все это целиком. Вероятно, лучше просто составить String список один раз, а затем использовать его?

Другой ваш вариант — создать функцию, которая принимает a Long и создает a String — в принципе, любую функцию, к которой вы переходите map , за исключением использования ее, когда она вам нужна. Если у вас очень большое количество Longs строк, и вам действительно не нужны все возможные String версии в памяти, просто генерируйте их всякий раз, когда вы их отображаете. Вы могли бы сделать это функцией расширения или свойством, если хотите, так что вы можете просто перейти

 fun Long.display() = "$this dollars"
val Long.dollaridoos: String get() = "$this.dollars"

print(number.display())
print(number.dollaridoos)
  

или создайте объект-оболочку, содержащий ваш список и предоставляющий доступ к строковой версии значений. Что бы у вас ни было


Кроме того, этот map подход более эффективен, чем создание ArrayList и добавление к нему, потому что он может выделить список с правильной емкостью с самого начала — произвольное добавление в список без размера будет продолжать увеличивать его, когда он станет слишком большим, тогда его придется копировать в другой (больший) массив … до тех пор, пока этоодин заполняется, затем это происходит снова…

Комментарии:

1. Частное расширение имело бы смысл, но его глобальное использование, похоже, нарушает предполагаемое использование расширений

2. Это был просто пример того, что вы могли бы сделать, если бы захотели, и если это сделает ваш код более читаемым. Вставьте его в любую область, которая кажется правильной! Вот для чего нужны расширения, для удобства чтения и добавления в классы, которые вы не контролируете (например Long ), но нет, вы, вероятно, не хотели Long бы, чтобы у s было свойство «создать строку цены» во всем вашем приложении … если вы этого не сделаете! Что бы ни работало для вас, в основном