Элемент предварительного ввода Kotlin

Я ищу альтернативу Kotlin для:
  (cons 1 '(2 3)) в lisp или
  1 : [2, 3] в haskell или
  1 :: List(2, 3) в scala,
(которые все приводят к sth, как [1, 2, 3])
поэтому я могу добавить элемент в List<T> (или любой другой список, который вы можете предложить).

Это также будет хорошо, если вы можете предоставить варианты O (1) head и tail Kotlin (я нашел только first())

Ответ 1

Любой класс, который реализует Deque, подходит вам, например LinkedList:

val linkedList = LinkedList(listOf(2, 3))
linkedList.push(1)
println(linkedList) // [1, 2, 3]

Создание списков через конструктор LinkedList(listOf(2, 3)) во многих местах может быть раздражающим, поэтому не стесняйтесь писать метод factory:

fun <T> linkedListOf(vararg elements: T): LinkedList<T> {
    return LinkedList<T>(elements.toList())
}

// Usage:
val list = linkedListOf(2, 3)
list.push(1)
println(list) // [1, 2, 3]

Ответ 2

Я думаю, что проще всего написать:

var list = listOf(2,3)
println(list) // [2, 3]
list = listOf(1) + list
println(list) // [1, 2, 3]

Нет конкретной реализации tail, но вы можете вызвать .drop(1), чтобы получить то же самое. Вы можете сделать это head\tail более общим, написав эти свойства расширения:

val <T> List<T>.tail: List<T>
  get() = drop(1)

val <T> List<T>.head: T
  get() = first()

Тогда:

val list = listOf(1, 2, 3)
val head = list.head
val tail = list.tail

Дополнительная информация: Функция хвоста списка Kotlin

Ответ 3

Просто, просто оберните элемент для добавления в List и затем используйте оператор + (или List.plus()), чтобы объединить два Lists:

val list1 = listOf(2, 3)        // [2, 3]
val list2 = listOf(1) + list1   // [1, 2, 3]

Для вашего второго вопроса, в Kotlin 1.2 есть:

List.first()
List.last()

Оба O (1)

Ответ 4

Чтобы как можно ближе к Lisp рассмотреть возможность использования неизменяемого связанного списка.

Вы можете использовать pcollections

val list = ConsPStack.from(listOf(2, 3))
val newList = list + 1
println(list)  // [2, 3]
println(newList) // [1, 2, 3]

Руководитель:

list.first() // 1
list[0] // 1

(к сожалению, эта вещь нуждается в одном распределении)

Хвост:

list - 0 // [2, 3]
list.subList(1) // [2, 3]  

Выглядит довольно уродливо.

Надеемся, что мы получим лучший API, когда kotlinx.collections.immutable будет готов. Это попытка создать стандартные неизменные коллекции Kotlin (а ​​не только доступные для чтения, которые у нас есть). На данный момент этот проект все еще находится на очень ранней стадии (мне не удалось найти структуру, поддерживающую эффективный preend/head/tail)

Ответ 5

Если вы по какой-то причине часто делаете это в своем коде, рассмотрите возможность добавления метода оператора расширения, такого как:

operator fun <T> T.plus(tail: List<T>): List<T> {
    val list = ArrayList<T>(1 + tail.size)

    list.add(this)
    list.addAll(tail)

    return list
}

Тогда ваш код может работать как Scala: 1 + listOf(2, 3)

Еще один способ добиться того же поведения, короче, но жертвуя памятью:

operator fun <T> T.plus(tail: List<T>): List<T> {
    return mutableListOf(this).apply {
        addAll(tail)
    }
}

Ответ 6

Это можно легко сделать с помощью расширенных функций, как показано ниже

Предопределяющий элемент

fun <T> MutableList<T>.prepend(element: T) {
    add(0, element)
}

Предварительный список

fun <T> MutableList<T>.prependAll(elements: List<T>) {
    addAll(0, elements)
}

Ответ 7

Я не совсем уверен, что вы хотите сделать, поэтому, пожалуйста, попробуйте одно из следующих.

Мутирующий список:

val list = mutableListOf(3, 2)
list.add(1)

Использование неизменяемого списка:

var list = listOf(3, 2)
list = list + 1