루비는 여러 값으로 정렬합니까?


78

해시 배열이 있습니다.

a=[{ 'foo'=>0,'bar'=>1 },
   { 'foo'=>0,'bar'=>2 },
   ... ]

먼저 각 해시의 'foo'로 배열을 정렬 한 다음 'bar'로 정렬하고 싶습니다. Google은 이것이 수행 방법이라고 말합니다.

a.sort_by {|h| [ h['foo'],h['bar'] ]}

그러나 이것은 나에게 ArgumentError "배열과 배열의 비교 실패"를 제공합니다. 이것은 무엇을 의미 하는가?


3
나를 위해 작동합니다. 이전 버전의 루비를 사용하고 있습니까?
Alex Wayne

2
게시 한 내용은 1.8.7에서 작동합니다.
Phrogz 2010

1
당신이 가지고 있다고 생각하는 데이터와 실제로 가지고있는 데이터가 같지 않을 수 있습니까?
Wayne Conrad

24
이 예외는 비교에 사용 된 결과 배열에 nil 및 비 nil 값이 모두 포함되어있을 때 발생합니다.
gucki

또한 Ruby는 부울 값을 비교할 수 없으므로이 오류가 발생할 수도 있습니다.
amoebe

답변:


84
a.sort { |a, b| [a['foo'], a['bar']] <=> [b['foo'], b['bar']] }

11
이것은 같은 것입니다. 보다 효율적인 방법으로 수행되는 것을 제외하고 Enumerable#sort_by(&block)는 대략 sort { |a,b| block.call(a) <=> block.call(b) }입니다. 이것이 작동하지만 작동 sort_by하지 않는다면 다른 것은 잘못된 것입니다.
wuputah 2010

간단한 키의 경우 정렬이 더 효율적입니다. 복잡한 키의 경우 sort_by가 더 효율적입니다.
dj2 2010

1
흠, 이제 "예상하지 않았는데도 객체가 없습니다!"라는 메시지가 표시됩니다. 오류. 내가 사용한 정확한 배열은 a=[{'foo'=>0,'bar'=>2},{'foo'=>0,'bar'=>1},{'foo'=>2,'bar'=>1},{'foo'=>1,'bar'=>0}].
herpderp 2010

나를 위해 작동합니다. >> a = [{ 'foo'=> 0, 'bar'=> 2}, { 'foo'=> 0, 'bar'=> 1}, { 'foo'=> 2, ' bar '=> 1}, {'foo '=> 1,'bar '=> 0}] => [{ "foo"=> 0, "bar"=> 2}, { "foo"=> 0, "bar"=> 1}, { "foo"=> 2, "bar"=> 1}, { "foo"=> 1, "bar"=> 0}] >> a.sort {| a, b | [a [ 'foo'], a [ 'bar']] <=> [b [ 'foo'], b [ 'bar']]} => [{ "foo"=> 0, "bar"=> 1}, { "foo"=> 0, "bar"=> 2}, { "foo"=> 1, "bar"=> 0}, { "foo"=> 2, "bar"=> 1} ]
dj2 2010

6
sort_by의 한 가지 장점은 더 DRY라는 것입니다.
Andrew Grimm

24

객체 중 하나에서 'foo'또는 'bar'필드 중 하나가 누락되었음을 의미합니다.

비교는 같은 것을 내려오고 nil <=> 2, 어떤 반환 nil(대신 -1, 0또는 1) 및 #sort_by처리하는 방법을 알고하지 않습니다 nil.

이 시도:

a.sort_by {|h| [ h['foo'].to_i, h['bar'].to_i ]}

13

게시 한 내용은 Ruby 1.8.7에서 작동합니다.

ruby-1.8.7-p302 > a = [{'foo'=>99,'bar'=>1},{'foo'=>0,'bar'=>2}]
 => [{"foo"=>99, "bar"=>1}, {"foo"=>0, "bar"=>2}] 

ruby-1.8.7-p302 > a.sort_by{ |h| [h['foo'],h['bar']] }
 => [{"foo"=>0, "bar"=>2}, {"foo"=>99, "bar"=>1}] 

ruby-1.8.7-p302 > a.sort_by{ |h| [h['bar'],h['foo']] }
 => [{"foo"=>99, "bar"=>1}, {"foo"=>0, "bar"=>2}] 

3

이 예외는 비교에 사용 된 결과 배열에 nil 및 비 nil 값이 모두 포함되어있을 때 발생합니다.


1

이 오류는 키가 불안정하고이를 기준으로 정렬하려고 할 때 나타납니다. 예:

[{'foo'=>99,'bar'=>1},{'foo'=>0,'bar'=>2, 'qwe' => 7}]
a.sort_by{|v| v['qwe']}
ArgumentError: comparison of NilClass with 7 failed

하려고

a.sort_by{|v| [v['qwe']].select{|k| not k.nil?}}

하지만 그것은 나를 위해 작동하지 않습니다

[v['index'],v['count'],v['digit'],v['value']]

숫자가 불안정한 곳


1

어레이와 어레이를 비교하지 못했습니다.

이것은 (적어도 내 경우에는) 배열 요소의 유형이 다르다는 것을 의미합니다. 모든 배열 항목이 동일한 시간 ( Integer예 :) 인지 확인했을 때 정렬이 작동하기 시작했습니다.


0

배열 압축 (nil 항목 제거)을 고려하고, 문자열 비교 인 경우 대소 문자를 구분하지 않는 정렬을 위해 값을 다운 케이스하십시오.

a.compact.sort_by { |h| [h['foo'].downcase, h['bar'].downcase] }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.