web-dev-qa-db-fra.com

Élément Kendlin prepend

Je recherche Kotlin alternative à:
(cons 1 '(2 3)) Dans LISP ou
1 : [2, 3] Dans haskell ou
1 :: List(2, 3) dans scala,
(qui aboutissent tous à quelque chose comme [1, 2, 3])
afin que je puisse ajouter un élément à un List<T> (ou à toute autre liste que vous pouvez proposer).

Ce sera aussi bien si on pouvait fournir O(1) head et tail alternatives Kotlin (je n'ai trouvé que first() )

13
Columpio

Toute classe qui implémente Deque vous conviendra, par exemple LinkedList:

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

La création de listes via le constructeur LinkedList(listOf(2, 3)) dans de nombreux endroits peut être ennuyeuse, alors n'hésitez pas à écrire la méthode d'usine:

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]
5
IRus

Je pense que le plus simple serait d'écrire:

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

Il n'y a pas d'implémentation tail spécifique, mais vous pouvez appeler .drop (1) pour obtenir la même chose. Vous pouvez faire cela head\tail plus générique en écrivant ces propriétés d'extension:

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

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

Ensuite:

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

Quelques informations supplémentaires: fonction de queue de la liste Kotlin

7
Strelok

Simple, enveloppez simplement l'élément à ajouter dans un List puis utilisez l'opérateur + (Ou List.plus()) pour concaténer les deux Lists:

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

Pour votre deuxième question, dans Kotlin 1.2 il y a:

List.first()
List.last()

Les deux sont O (1)

2
Luzian

Si vous le faites souvent dans votre code pour une raison quelconque, envisagez d'ajouter une méthode d'opérateur d'extension telle que:

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
}

Ensuite, votre code pourrait fonctionner comme Scala: 1 + listOf(2, 3)

Une autre façon d'obtenir le même comportement, plus courte mais sacrifie de la mémoire:

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

Pour être aussi proche de LISP que possible, envisagez d'utiliser une liste chaînée immuable.

Vous pouvez utiliser pcollections

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

Tête:

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

(malheureusement, cette chose a besoin d'une allocation)

Queue:

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

Ça a l'air plutôt moche.

J'espère que nous aurons une meilleure API quand kotlinx.collections.immutable sera prêt. C'est un effort pour créer des collections immuables Kotlin standard (pas seulement celles en lecture seule que nous avons actuellement). Pour l'instant, ce projet est encore à un stade très précoce (je n'ai pas pu trouver de structure qui prend en charge un prépend/tête/queue efficace)

0
xap4o