2012-08-30 1 views
2

, to_f 잘 작동하지 않습니다더 큰 버전 번호를 찾는 방법은 무엇입니까? 이 버전 문자열을 비교하면

> "1.5.8".to_f > "1.5.7".to_f 
    => false 

문자열 비교는 항상 올바른 더 나은,하지만 :

> "1.5.8" > "1.5.7" 
    => true 

> "1.5.8" > "1.5.9" 
    => false 

> "1.5.8" > "1.5.10" # oops! 
    => true 

어떻게 제대로 버전 문자열을 비교?

+0

방학이 부분에서, 정수로 부품을 주조하고 개별적으로 비교합니다. –

+0

문자열을 직접 비교하는 것이 때로는 잘 수행되지 않습니다. 문자열이 다른 길이이고 가장 짧은 길이까지 비교할 때 문자열이 같으면 더 긴 문자열이 더 짧은 문자열보다 큰 것으로 간주됩니다. 그래서, 정의에 따르면 : ** '1.5.8'> '1.5.10'# => true ** 이후 4 번째 char 8> 1 ** '1.5.1'> '1.5. 10 '# => false **, 이후 4 번째 char 1 == 1과 후자의 문자열은 더 길다 –

+0

@ JingLi : 고마워, 모자. :) –

답변

4

아이디어 :

: (우주선 연산자 Object#<=> 일명) compare처럼 동작하지만, 사용자 정의 블록을 취하는 Object#compare_by 방법을 만들
class Object 
    def compare_by(other) 
    yield(self) <=> yield(other) 
    end 
end 

>> "1.5.2".compare_by("1.5.7") { |s| s.split(".").map(&:to_i) } 
#=> -1 

compare 방법을 기반으로 더욱 구체적인 방법을 사용할 수도 있습니다.

class String 
    def compare_by_fields(other, fieldsep = ".") 
    cmp = proc { |s| s.split(fieldsep).map(&:to_i) } 
    cmp.call(self) <=> cmp.call(other) 
    end 
end 

>> "1.5.8".compare_by_fields("1.5.8") 
#=> 0 
+0

나는이 같은 훌륭한 배열의 배열을 비교할 수 있는지 몰랐다. – oldergod

+0

@oldergod : 배열을 <=>으로 비교할 수 있지만'Comparable' 모듈은 기본적으로 포함되지 않으므로'[1,2]> [4,2]'를 쓸 수 없습니다. 나는 왜 그런지 이해하지 못했습니다. (물론 당신이 직접 포함시킬 수 있습니다) – tokland

0

우선 버전의 다른 부분을 분할하여 시작 :

v1 = "1.5.8" 
v2 = "1.5.7" 
v1_arr = v1.split(".") 
=> ["1", "5", "8"] 
v2_arr = v2.split(".") 
=> ["1", "5", "7"] 
v1_arr.size.times do |index| 
    if v1_arr[index] != v2_arr[index] 
    # compare the values at the given index. Don't forget to use to_i! 
    break 
    end 
end 
+3

이것은 C가 아닙니다. 루비를 쓸 수 있습니다 :) –

+0

사실 C가 아니기 때문에 C에서 비슷한 해결책을 제공하는 것을 멈추게하지 않습니다. "루비"스타일로 더 짧은 해결책을 제공하는 방법을 생각할 수 없었습니다. –

+0

@ tokland의 답변을 확인하십시오. 새로운 것을 배울지도 모른다. –

4

개인적으로 나는 단지 Versionomy 보석을 사용할 것입니다.이 특별한 바퀴 IMHO를 재발견 할 필요가 없습니다.

예 :

require 'versionomy' 
v1 = Versionomy.parse("1.5.8") 
v2 = Versionomy.parse("1.5.10") 
v2 > v1 
#=> true 
관련 문제