#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 было свойство «создать строку цены» во всем вашем приложении … если вы этого не сделаете! Что бы ни работало для вас, в основном