2016-03-04 11 views
12

私はList<T>にtail関数を見つけようとしていますが、何も見つかりませんでした。私はこれをやり終えた。Kotlinリストtail関数

fun <T> List<T>.tail() = this.takeLast(this.size -1) 

これを行うより良い方法はありますか?

答えて

22

KotlinにはList<T>.tail()機能が組み込まれていないため、独自の拡張機能を実装する方法は唯一の方法です。あなたの実装が完全に罰金ですが、それは少し単純化することができます。

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

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

そして、同じようにそれを使用します:

fun <T> List<T>.tail() = drop(1) 

または、代わりに拡張機能のを、あなたは拡張プロパティを定義することができます

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

リストをコピーしたくない場合(多くの場合、CPUキャッシュと小さなリストは問題ありません)、拡張子https:/ /docs.oracle.com/javase/7/docs/api/java/util/List.html#subList(int,%20int)(下記のコメントの@hotkey) –

3

あなたと@Vladimir Mironovのソリューションになりますが、自動的に元のリストの熱心なコピーが作成されますent)、大きなリストの場合は非常に時間がかかることがあります。私は、インデックスの調整を使用して最初の要素を無視して、ラップ1にその代表者がそのメソッドのラッパーListクラスでそれを定義します

private class TailList<T> (private val list: List<T>) : List<T> { 
    override val size: Int 
     get() = list.size -1 

    override fun isEmpty(): Boolean = size == 0 

    override fun iterator(): Iterator<T> = listIterator() 
    override fun listIterator(): ListIterator<T> = list.listIterator(1) 
    override fun listIterator(index: Int): ListIterator<T> = list.listIterator(index + 1) 
    override fun subList(fromIndex: Int, toIndex: Int): List<T> = list.subList(fromIndex + 1, toIndex + 1) 
    override fun lastIndexOf(element: T): Int = list.lastIndexOf(element) - 1 
    override operator fun get(index: Int): T = list[index + 1] 

    // The following member functions require the copy of a new list 
    override fun containsAll(elements: Collection<T>): Boolean = tailList.containsAll(elements) 
    override fun contains(element: T): Boolean = tailList.contains(element) 
    override fun indexOf(element: T): Int = tailList.indexOf(element) 

    private val tailList by lazy { ArrayList(this) } // makes a proper copy the elements this list represents 
} 

コメントはまだ熱心になって終わるの後にあなたはセクション内の機能に気づくことコピー。私はこれを単純化のためだけにしました。メモリのために、私はlazytailListプロパティを作成しました。

何らかの委任を行うのではなく、手動でコレクションを反復処理することで実装できます。それがあなたが好むものなら、私はあなたがそれを理解できると確信しています。それと

、頭と尾のプロパティは、このなる:あなたは本当にそれを必要とする場合、彼らは熱心なコピーを作成しないように、私は最後の3つのメンバ関数を作るために更新を追加することができます

val <T> List<T>.tail: List<T> 
    get() = 
     if(this.isEmpty()) 
      throw IllegalStateException("Cannot get the tail of an empty List") 
     else 
      TailList(this) 

val <T> List<T>.head: T 
    get() = this[0] // or first() 

EDIT: 注:Kotlinは、これまで続いた規則に従った場合Listにその機能のすべてが熱心なコピーを作成するので、あなたは、このように、Listのしっぽを怠惰にすることはないだろう。代わりに、特にあなたがheadtailを繰り返し使用してリストを反復している場合は、何とかこのラッパーのアイデアをSequenceに試みることができますか? Sequenceの全体的な存在は、コレクションに対する怠惰な作業のためです。

EDIT 2: 明らかに、sublist()はビューを作成するため、すでにレイジーです。本質的には、サブリスト用の実装を作成する方法を教えました。

だから、その場合はtail関数にsublist()を使用してください。

+1

Javaのサブリストを使用するだけではどうですか?それはまったく同じことです、元のリストのビューを作成します。 https://docs.oracle.com/javase/7/docs/api/java/util/List.html#subList(int,%20int) – hotkey

+0

これはシーケンスではありませんか? –

+1

@hotkeyサブリストがビューであることはわかりませんでした。知っておいてよかった。 –

関連する問題