2016-11-25 5 views
0

入力配列に問題があり、CodeWarsでRubyチャレンジを試みました。 関数likees :: [String] - > Stringを実装します。これは、入力配列を取る必要があり、アイテムを好む人の名前を含みます。例に示すように、それは表示テキストを返す必要があります。[]に対しては未定義のメソッドsplit:Array Rubyコードワード "誰が好きですか?" Kata

likes [] // must be "no one likes this" 
likes ["Peter"] // must be "Peter likes this" 
likes ["Jacob", "Alex"] // must be "Jacob and Alex like this" 
likes ["Max", "John", "Mark"] // must be "Max, John and Mark like this" 
likes ["Alex", "Jacob", "Mark", "Max"] // must be "Alex, Jacob and 2 others like this" 

私のtry-コードは次のとおりです。

def likes(names) 
    arr = Array.[](names.split(/\W+/)) 
    if arr.size == 0 
    var = "no one likes this" 
    return var 
    elsif arr.size == 1 
    return arr[0]+ " likes this " 
    elsif arr.size == 2 
    return arr[0] + "and #{arr[1]} likes this " 
    elsif arr.size == 3 
    return " #{arr[0]}, #{arr[1]} and #{arr[2]} likes this " 
    elsif arr.size >3 
    return "#{arr[0]}, #{arr[1]} and #{arr.size-1} likes this " 
    end 
end 

そしてそれはリターンをコンパイルするものです:

`likes': undefined method `split' for []:Array (NoMethodError) 
from `block in 
' 
from `block in describe' 
from `measure' 
from `describe' 
from ` 
' 

click to see image with error

+0

アレイのための 'split'と呼ばれる方法はありません。 – vgoff

+0

コメントを@vgoffで展開するには:すでにメソッドに配列を渡しています。 'names'が名前のリストで構成された文字列だった場合、'#split'を使って配列に分割する必要があります。しかし、 'names'は配列なので、'#split'メソッドを含むコード行を削除してメソッド全体で 'arr'を' names'に置き換えることができます。 – moveson

+0

Rubyの行末コメントは '#'で始まります。 '//'はサポートされていません。 –

答えて

1

このコードには、動作させる前に解決する必要のある混乱がたくさんあります。配列の塊を抜き出したい場合は、slice、または最初の2つを抽出する単純な配列表記names[0,2]を使うことができます。

とき、あなたはそれが頻繁に調べるために、コードのビットを追加するのと同じくらい簡単だ受けているのか、引数好奇心:あなたが受け取ったオブジェクトの種類が表示されます何かをダンプします

p names.class.inspect 

。この場合、配列です。

初心者にとっては、あまりにもリテラルなコードという点では、特定の配列の長さをテストする非常に狭いケースのように考えるのは間違いです。実際には3つ以上の条件、誰もいない、デフォルトのケースという3つの条件しかありません。その権利を変更し、取得フレージングに

まず焦点:これは枝の最小数とかなり簡潔なアプローチであり、あなたがそれを行うかもしれないいくつかの方法がありますが、

def name_list(names) 
    if (names.empty?) 
    # An empty list means: 
    'nobody' 
    else 
    # Special case for the last element in the list, so pull it off 
    *names, last = names 

    # If there's more than two names remaining then change the 
    # phrasing of the last element to indicate "N others" 
    if (names.length > 2) 
     last = '%d others' % (names.length - 1) 
    end 

    # Join these together in the "X, Y, and Z" format. 
    (names[0,2] + [ 'and ' + last ]).join(', ') 
    end 
end 

。あなたは自分自身を繰り返すことを避けたい、それがバグの仕組みです。共通の動作を共通のコードに統合します。 「これが好き」の部分はそのような例の1つです。あなたはフレージングそれを行うには一箇所がありますを変更したい場合は

def likes(names) 
    name_list(names) + ' liked this' 
end 

そのように、あなたは、あなたが扱っている他の状況でこのメソッドを再使用することができます。

今、あなたはこれを行うことができます名前や物のリスト。

1

私はこのように書いています。

def say_names(name_arr) 
    case name_arr.size 
    when 0 then "no one likes this" 
    when 1 then "%s likes this"   % name_arr 
    when 2 then "%s and %s like this"  % name_arr 
    when 3 then "%s, %s and %s like this" % name_arr 
    else "%s, %s and %d others like this" % (name_arr[0,2] + [name_arr.size-2]) 
    end 
end 

say_names [] 
    #=> "no one likes this" 
say_names ["Peter"] 
    #=> "Peter likes this" 
say_names ["Jacob", "Alex"] 
    #=> "Jacob and Alex like this" 
say_names ["Max", "John", "Mark"] 
    #=> "Max, John and Mark like this" 
say_names ["Alex", "Jacob", "Mark", "Max", "Trixie"] 
    #=> "Alex, Jacob and 3 others like this" 

このメソッドを書き込む方法は少し短くなるかもしれませんが、私はこれを読むのが好きです。

0

あなたの元のコードを使用して、簡単な三元表現

def likes(names) 
    arr = names.empty? ? [] : Array.[](names.split(/\W+/)) 
    if arr.size == 0 
    var = "no one likes this" 
    return var 
    elsif arr.size == 1 
    return arr[0]+ " likes this " 
    elsif arr.size == 2 
    return arr[0] + "and #{arr[1]} likes this " 
    elsif arr.size == 3 
    return " #{arr[0]}, #{arr[1]} and #{arr[2]} likes this " 
    elsif arr.size >3 
    return "#{arr[0]}, #{arr[1]} and #{arr.size-1} likes this " 
    end 
end 

はトリックを行う必要があります追加。

ruby​​は暗黙のうちに評価された最後のものを返すので、もっときれいな方法はすべてのreturn文を削除することです。そのように:

def likes(names) 
     arr = names.empty? ? [] : Array.[](names.split(/\W+/)) 
     if arr.size == 0 
     "no one likes this" 
     elsif arr.size == 1 
     arr[0]+ " likes this " 
     elsif arr.size == 2 
     arr[0] + "and #{arr[1]} likes this " 
     elsif arr.size == 3 
     "#{arr[0]}, #{arr[1]} and #{arr[2]} likes this " 
     elsif arr.size >3 
     "#{arr[0]}, #{arr[1]} and #{arr.size-1} likes this " 
     end 
    end 

最後に、あなたはしかし、あなたのような読みやすさを犠牲にすることになる、2行でこれを置くことができます。

def likes(names) 
    arr = names.empty? ? [] : Array.[](names.split(/\W+/)) 
    arr.size == 0 ? "no one likes this" : arr.size == 1 ? arr[0]+ " likes this " : arr.size == 2 ? arr[0] + "and #{arr[1]} likes this" : arr.size == 3 ? "#{arr[0]}, #{arr[1]} and #{arr[2]} likes this " : "#{arr[0]}, #{arr[1]} and #{arr.size-1} likes this " 
end 
関連する問題