2017-12-04 5 views
0

スライスの要素を数えるための単純な関数を作成しようとしています(lenのように)単純な(追加のライブラリなしで)、再帰を伴う必要があります。問題は、スライスが空であることを確認しようとするときです(ヌルです)。自分のlen関数がGoで再帰を伴う

package main 
import "fmt" 

func main() { 
    x := []int{1, 2, 3} 
    fmt.Println(len2(x)) 
} 
func len2(s []int) int { 
    if s == nil { 
    return 0 
    } 
    return 1 + len2(s[1:]) 
} 

結果は、この例では '3'になるはずです。

場合の==はnilで壊れて:あなたは有効な終了条件を持っていないので、それはパニック

panic: runtime error: slice bounds out of range 
+0

私は自分のlenをビルドすることを忘れました。私はビルドインlen関数を使用することはできません。 –

+0

あなたは単にこれを行うことはできません**。これは完全に不可能です:再帰は終了しなければなりません(あなたのコードで 's == nil'の場合)、これは組み込みのlen関数でのみ行うことができます。 – Volker

答えて

0

次はlenよりも優れた性能を持つソリューションが、余分なライブラリを使用していない実装ではありません。ここで長さ

func len2(s []int) (count int) { 
    defer func() { 
     if r := recover(); r != nil { 
      count = 0 
     } 
    }() 

    return 1 + len2(s[1:]) 
} 

を見つけるために、再帰に依存するサンプルコード

です
package main 

import "fmt" 

func main() { 
    var x []int = nil 
    var x1 = []int{1, 2, 3, 4} 
    var x2 = []int{} 
    var x3 = make([]int, 10, 20) 
    fmt.Println(len2(x)) 
    fmt.Println(len2(x1)) 
    fmt.Println(len2(x2)) 
    fmt.Println(len2(x3)) 
} 

func len2(s []int) (count int) { 
    defer func() { 
     if r := recover(); r != nil { 
      count = 0 
     } 
    }() 

    return 1 + len2(s[1:]) 
} 

playground

+0

否定票の理由を記入してください。特に回答が受け入れられた回答の場合には –

2

を。

len2()が空でないスライスで呼び出された場合、s[1:]のようにスライスして実行時のパニックになります。代わりにnilスライスをチェックする

は、スライスが0にその長さを比較することによって、空であるかどうかを確認:

func len2(s []int) int { 
    if len(s) == 0 { 
     return 0 
    } 
    return 1 + len2(s[1:]) 
} 

Go Playground上でそれを試してみてください。

あなたは(あなたはすでにあなたのソリューションで行った)組み込みlen()機能を使用できない場合は、for ... rangeを使用することがあります。

func len2(s []int) int { 
    size := 0 
    for i := range s { 
     size = i + 1 
    } 
    return size 
} 

Go Playgroundでこれを試してみてください。

そして、それは再帰的でなければならない場合には、例えば:

func len2(s []int) int { 
    size := 0 
    for range s { 
     size = 1 + len2(s[1:]) 
     break 
    } 
    return size 
} 

Go Playgroundでこれを試してみてください。

しかし、これらは組み込みのlen()を使用する場合と比べてひどい解決策であることがわかります。

-1

あなたがlen()FUNCを使用したくない場合は、cap()

func main() { 
    x := []int{1, 2, 3} 
    fmt.Println(len2(x)) 
} 

func len2(s []int) int { 

if cap(s) == 0 { 
    return 0 
} 

    return 1 + len2(s[1:]) 
} 

Try it again

オリジナル回答使用することができます。array(スライスかどうかを確認するために、

を)が空の場合は、関数を使用する必要があります。len()

if len(s) == 0 { 
    return 0 
    } 

Try it

+0

私は独自のlen関数を作成したい - それは埋め込みlen関数を使用したくないということです。 –

+0

すべての実装で動作する言語仕様では保証されません。 – Volker

-1

ここで再帰せずに残すことができる場合は、len()を使用しない関数があります。再帰的に高速化して再スライスする必要があります。

func len2(s []int) (count int) { 
    for i := range s { 
    count = i + 1 
    } 
} 
+0

同じ範囲のループ保護を使用する再帰を使用する代わりに、実際に呼び出さずに範囲演算子をghetto 'len'呼び出しとして使用します'len'):https://play.golang.org/p/KeXUfnJAr3 – Kaedys