2009-12-23 5 views
6

문자열을 먼저 정렬 한 다음 숫자로 정렬하고 싶습니다. 어떻게해야합니까?Ruby에서 문자열과 숫자 정렬

+1

귀하의 질문은 충분 정말 특정되지 않습니다. 무엇을 정렬하려고합니까? 문자열 또는 문자? 그리고 당신은 항상 글자가 숫자보다 낮게 정렬되기를 원한다는 것을 의미합니까? 문자열에 문자와 숫자가 혼합되어 있으면 어떻게 될까요? 또는 문자가 숫자 앞에 정렬되는 사전 분류를 원하십니까? –

+0

질문을 명확히 해주시겠습니까? 원하는 정렬 순서의 예제를 제공 할 수 있습니까? –

+0

배열에있는 내용은 무엇입니까? – klochner

답변

15

까다로운 종류를 해결하기위한 일반적인 트릭은 기본 및 보조 정렬 순서를 갖는 배열을 반환 블록 (그리고, 당신이 그것을 필요로하는 경우에, 차 등)

a = ['foo', 'bar', '1', '2', '10'] 
b = a.sort_by do |s| 
    if s =~ /^\d+$/ 
    [2, $&.to_i] 
    else 
    [1, s] 
    end 
end 
p b # => ["bar", "foo", "1", "2", "10"] 

으로, #sort_by을 사용하는 것입니다 이것은 배열 비교가 Ruby에 의해 정의 된 방식 때문에 효과가 있습니다. 비교는 Array#<=> 방법으로 정의됩니다.

배열은 "요소 방식"방식으로 비교됩니다. ary의 첫 번째 요소는 < => 연산자를 사용하여 other_ary의 첫 번째 요소와 비교되고, 두 번째 요소는 각각 ... 등의 비교 결과가 0이 아닌 경우 (즉, 두 개의 해당 요소가 같지 않으면), 그 결과는 전체 배열 비교를 위해 반환됩니다.

+0

'Float' 객체가있는 경우 처리 방법은 무엇입니까? 컬렉션에'Float's가 포함되어 있으면 깨지기 시작합니다. 기본적으로 코드를 사용하고 있지만 Float 객체에 대해 손상되고 있습니다 .. –

17

숫자와 숫자가 섞인 배열을 먼저 정렬하고 순서대로 정렬 한 다음 순서대로 두 번째 문자열을 정렬합니다.

>> a = [1, 2, "b", "a"] 

>> a.partition{|x| x.is_a? String}.map(&:sort).flatten 
=> ["a", "b", 1, 2] 
+0

대답에 대한 감사, – s84

+0

나는 자러 갔으면합니다. 사실, 배열은 문자열 일뿐입니다. 문자열은 문자의 "숫자"로 시작될 수 있습니다. – s84

+5

'partition ... flatten' 콤보의 엄청난 사용. – akuhn

2

일반적으로 알파벳순으로 번호가 매겨집니다. 글자가 숫자 이전에 알파벳순으로 배열되는 것을 알파벳순으로 사용하려면 사용되는 비교 함수를 변경해야합니다.

# I realize this function could be done with less if-then-else logic, 
# but I thought this would be clearer for teaching purposes. 
def String.mysort(other) 
    length = (self.length < other.length) ? self.length : other.length 
    0.upto(length-1) do |i| 
    # normally we would just return the result of self[i] <=> other[i]. But 
    # you need a custom sorting function. 
    if self[i] == other[i] 
     continue # characters the same, skip to next character. 
    else 
     if self[i] ~= /[0-9]/ 
     if other[i] ~= /[0-9]/ 
      return self[i] <=> other[i] # both numeric, sort normally. 
     else 
      return 1 # self is numeric, other is not, so self is sorted after. 
     end 
     elsif other[i] ~= /[0-9]/ 
     return -1 # self is not numeric, other is, so self is sorted before. 
     else 
     return self[i] <=> other[i] # both non-numeric, sort normally. 
     end 
    end 
    end 

    # if we got this far, the segments were identical. However, they may 
    # not be the same length. Short sorted before long. 
    return self.length <=> other.length 
end 

['0','b','1','a'].sort{|x,y| x.mysort(y) } # => ['a', 'b', '0', '1'] 
0

혼합 사례와 숫자를 정렬하려는 경우 지구상의 일부 사용자 만 독점 응용 프로그램 외부에서이를 수행 할 수 있습니다. 그것은 빨판 펀치가있는 비밀입니다. 대소 문자 (대문자와 소문자)를 섞을 때까지 정렬을 쉽게하는 qsort를 사용해야합니다. 그렇다면 대학, 서적, 인터넷은 교수형에 처해 있습니다. 이 해킹은 금으로 무게가 나가기에 충분하며 모든 이유로 프로그래밍의 황동 반지입니다.

숫자로 단어를 정렬하려면 숫자를 문자열로 변환해야합니다. 대문자를 사용하여 미리 분류해야합니다. 적음에 "개미", "개미"및 "anT"라는 단어가있는 경우 모두 대문자 정렬 목록에 "ANT"라는 단어를 가리켜 야합니다. 그런 다음 세 단어 ("Ant", "ant"및 "anT")의 목록 (배열)을 만들고 qsort를 타이 브레이커로 사용하여 정렬합니다.

그런 다음 최종 정렬 배열에 삽입합니다. 디자인 상으로는 상당히 어렵습니다. "A"는 ascii에서 65이고 'a'는 'Z'와 'a'사이에 많은 가비지 문자가있는 97입니다. 우연이 아닙니다! 내가 말한 음모 야!

당신은 소트 테이블을 생성 할 수있는 더욱 올바로 수행 기 등 문자 :

A, A, B, B, C, C, D, D, E, E, F, F, G, g, 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 (예 : H, I, J, J, K, K, L, I, M, 83 84 85 86 87 88 89 90 91 92 ...

""(공백) ascii 32부터 128까지 시작하는이 블록 주위에 표를 작성하십시오. A 65가 순서대로 번호 순서를 바꾸기를 원할 것입니다 보기 전용.

이렇게하면 쉽게되지만 대부분의 프로그래밍 언어의 매크로 외부에서 성능이 저하 될 수 있습니다. 행운을 빕니다!

1

다음은 다소 장황한 답변입니다. 배열을 두 개의 하위 배열로 나눕니다 : 문자열과 숫자를 정렬하고 정렬하십시오.

array = [1, 'b', 'a', 'c', 'd', 2, 4, 3] 
strings = [] 
numbers = [] 
array.each do |element| 
    if element.is_a? String 
    strings << element 
    else 
    numbers << element 
    end 
end 
sorted_array = strings.sort + numbers.sort 
sorted_array # ['a', 'b', 'c', 'd', 1, 2, 3, 4] 
2
a = ['1', '10', '100', '2', '42', 'hello', 'x1', 'x20', 'x100', '42x', '42y', '10.1.2', '10.10.2', '10.8.2'] 
a.map {|i| i.gsub(/\d+/) {|s| "%08d" % s.to_i } }.zip(a).sort.map{|x,y| y} 
# => ["1", "2", "10", "10.1.2", "10.8.2", "10.10.2", "42", "42x", "42y", "100", "hello", "x1", "x20", "x100"] 
+1

a.sort_by {| i | i.gsub (/ \ d + /) {| s | "% 08d"% s.to_i}} – bluexuemei

+0

@bluexuemei 아 멋지 네요. 시원한 – neoneye

관련 문제