2016-12-09 1 views
1

Ruby에서 다음 코드를 작성했지만 계속 NoMethodError: undefined method '>' for nil:NilClass이됩니다. 왜 >은 방법이라고 생각하십니까?ruby보다 큰 부호 오류가 발생했습니다

def count_positives_sum_negatives(lst) 
    pos = 0 
    neg = 0 
    for i in 0..lst.length 
    if lst[i] > 0 
     pos += 1 
    elsif lst[i] < 0 
     neg += 1 
    end 
    end 
    return [pos, neg] 
end 
+0

색인이 하나 씩 꺼져 있습니다 (내 대답 참조). – manonthemat

+0

이 방법은 긍정과 부정을 계산합니다. 그것은 네거티브를 합하지 않습니다. 'count_positives_sum_negatives'라고하는 이유는 무엇입니까? 호기심, 알았지? –

+0

@Aetherus는 당신에게 최고의 "Ruby way"대답을주었습니다. 그걸 사용하십시오. – moveson

답변

2

을합니다. 제발, 저를 오해하지 마십시오. 몇 년 전에 Ruby를 시작했을 때 들었던 것을 반복하고 있습니다. Ruby를 배우는 것은 Ruby 구문을 사용하는 것 이상입니다. Ruby 코어를 탐색하고 Ruby 방식으로 작업 해보십시오.

이것은 정확히 여기서 발생합니다. 질문에 표시된 코드는 Ruby 방식과는 거리가 멀다. 또한 @manonthemat에 의해 주어진 답안의 코드도 있습니다.

def count_positives_sum_negatives(lst) 
    result = [0,0] 
    lst.each { |el| (el > 0) ? result[0] += 1 : result[1] += 1 } 
    result 
end 

또는 더 나은 :

단축 할 수있는 두 가지 경우 모두

def count_positives_sum_negatives(lst) 
    lst.each_with_object([0,0]) { |el,arr| (el > 0) ? arr[0] += 1 : arr[1] += 1 } 
end 

,

puts count_positives_sum_negatives([5,7,-1,-4,4,4,5,-3]) 

를 실행

[5,3] 
,536 초래

each_with_object을 사용하는 두 번째 형식은 첫 번째 형식보다 훨씬 좋습니다. 블록 내부에서 사용하기 위해 배열이나 해시를 선언하면 Ruby에서 코드 냄새로 간주됩니다.

나는 방법의 이름 (count_positives_sum_negatives)이 좋지 않다는 것을 지적하고 싶습니다. 이 방법은 포지티브와 네거티브를 모두 계산하고 그 중 아무 것도 합하지 않기 때문에 메서드가 수행하는 작업을 나타내지는 않습니다. 확실히 count_positives_and_negatives은 더 나은 이름입니다.

한편, @manonthemat는 범위를 기준으로 인덱스를 반복하는 것보다 each을 사용하는 것이 훨씬 낫다는 것을 지적하면서 완전히 옳습니다. 블록에 실제로 색인이 필요한 경우이를 제공하는 방법은 each_with_index입니다.

1

은 내가 루비를 사용했습니다 이후 오랜만이야,하지만 난 각

def count_positives_sum_negatives(lst) 
    pos = 0 
    neg = 0 
    lst.each { |el| 
    if el > 0 
     pos += 1 
    elsif el < 0 
     neg += 1 
    end 
    } 
    return [pos, neg] 
end 

그러나 귀하의 질문에 대답하기 위해, 색인이 꺼져를 사용하여 반복하는 선호하는 방법을 기억합니다. ..에는 오른쪽에있는 내용이 포함되어 있습니다. 이 경우 목록의 길이는 마지막 색인보다 하나 더 높습니다. 그래서 그 오류 메시지가 나타납니다.

당신은 여전히 ​​당신을위한 루프, 그러나 다만 추가 다른. 사용할 수 있습니다, 그래서 내가 이런 말을 할 때 나는 루비 마스터 오전 척하고 있지 않다 for i in 0...lst.length

+0

이 답변이 작동하는 동안, Ruby 방식은 문제를 해결할 다른 방법이 있다면'each'를 사용하지 않는 것이 좋습니다. 여기 @Aetherus의 답변에서 더 잘 해결되었습니다. – moveson

2

문제는 lst[lst.length]은 항상 nil입니다. 예를 들어 lst이 [1] 인 경우 lst[lst.length]lst[1]nil이됩니다.

nil은 개체이므로 메서드가있을 수 있습니다. nil > 0으로 전화하면 Ruby는 이것을 nil.>(0)으로 해석합니다 (>이 방법 임). nil에는 > 메서드가 없으므로 NoMethodError이 있습니다.

경계 검사의 골칫거리를 제거하려면 for 루프를 사용하지 않아야합니다. 모듈 Enumerable에서

def count_positives_sum_negatives(lst) 
    positives, negatives = lst.partition(&:positive?) 
    [positives.size, negatives.reduce(:+)] 
end 
모두 partition

reduce 온 : 여기 내 구현입니다.그룹에 0을 넣었습니다. 왜냐하면 그들은 합계의 결과에 영향을 미치지 않기 때문에 카운트 결과에 영향을 미치기 때문입니다.

+1

OP의 메소드 이름이'count_positives_sum_negatives'이지만, 그의 원래 코드는 둘 다 계산됩니다. 그것이 의도라면,이 코드의 세 번째 줄은'[positives.size, negatives.size]'로 대체 될 것입니다. 아니면 우리가 일을 세고 있기 때문에, 별칭''positives.count, negatives.count '를 사용하십시오. – moveson

+0

동의 함, @moveson. 나는 그 질문에 대해 그것에 대해 논평하고 나의 대답에 그것을 언급하면서 새로운 이름을 제안했다. –

+0

@moveson은 이름 변경에 동의하지만'count'는'size'의 별칭이 아닙니다 (그러나'size'는'length'의 별명입니다). 'size'는 실제로'count'보다 훨씬 빠릅니다. –

관련 문제