문제

해시 배열이 있고 고유 한 값을 원합니다. 부름 Array.uniq 내가 기대하는 것을주지 않습니다.

a = [{:a => 1},{:a => 2}, {:a => 1}]
a.uniq # => [{:a => 1}, {:a => 2}, {:a => 1}]

내가 예상 한 곳 :

[{:a => 1}, {:a => 2}]

그물을 찾아서, 나는 내가 행복한 솔루션을 생각해 내지 않았다. 사람들은 재정의를 추천했습니다 Hash.eql? 그리고 Hash.hash, 그 이유는 무엇이기 때문입니다 Array.uniq 쿼리입니다.

편집 : 현실 세계에서 이것에 부딪친 곳에서 해시는 약간 더 복잡했습니다. 그것들은 여러 필드를 가진 구문 분석 JSON의 결과였으며, 그 중 일부는 값도 해시였습니다. 고유 한 값을 필터링하고 싶었던 결과의 배열이있었습니다.

나는 재정의를 좋아하지 않는다 Hash.eql? 그리고 Hash.hash 해결책, 재정의해야하기 때문에 Hash 내 배열의 각 항목에 대해 전 세계적으로 재정의하십시오. 정의를 변경합니다 Hash 각 항목의 경우 각 항목의 내부에 중첩 된 해시가있을 수 있기 때문에 각 항목은 번거 롭습니다.

바꾸다 Hash 전 세계에는 특히 일시적으로 수행 된 경우 잠재력이 있습니다. 나는 이전 정의를 저장하고 복원하는 다른 클래스 또는 도우미 기능을 구축하고 싶지만, 이것이 실제로 필요한 것보다 더 복잡하다고 생각합니다.

사용 inject 재정의에 대한 좋은 대안 인 것 같습니다 Hash.

도움이 되었습니까?

해결책

나는 전화를 통해 내가 원하는 것을 얻을 수 있습니다 inject

a = [{:a => 1},{:a => 2}, {:a => 1}]
a.inject([]) { |result,h| result << h unless result.include?(h); result }

이것은 돌아올 것입니다 :

[{:a=>1}, {:a=>2}]

다른 팁

루비 1.8.7+는 예상 한 내용을 반환합니다.

[{:a=>1}, {:a=>2}, {:a=>1}].uniq
#=> [{:a=>1}, {:a=>2}] 

나는 비슷한 상황이 있었지만 해시는 열쇠를 가지고있었습니다. 분류 방법을 사용했습니다.

내 말은:

배열이 있습니다.

[{:x=>1},{:x=>2},{:x=>3},{:x=>2},{:x=>1}]

당신은 그것을 분류합니다 (#sort_by {|t| t[:x]}) 그리고 이것을 얻으십시오 :

[{:x=>1}, {:x=>1}, {:x=>2}, {:x=>2}, {:x=>3}]

이제 Aaaron Hinni의 약간 수정 된 답변 버전 :

your_array.inject([]) do |result,item| 
  result << item if !result.last||result.last[:x]!=item[:x]
  result
end

나는 또한 시도했다 :

test.inject([]) {|r,h| r<<h unless r.find {|t| t[:x]==h[:x]}; r}.sort_by {|t| t[:x]}

그러나 매우 느립니다. 다음은 내 벤치 마크입니다.

test=[]
1000.times {test<<{:x=>rand}}

Benchmark.bmbm do |bm|
  bm.report("sorting: ") do
    test.sort_by {|t| t[:x]}.inject([]) {|r,h| r<<h if !r.last||r.last[:x]!=h[:x]; r}
  end
  bm.report("inject: ") {test.inject([]) {|r,h| r<<h unless r.find {|t| t[:x]==h[:x]}; r}.sort_by {|t| t[:x]} }
end

결과:

Rehearsal ---------------------------------------------
sorting:    0.010000   0.000000   0.010000 (  0.005633)
inject:     0.470000   0.140000   0.610000 (  0.621973)
------------------------------------ total: 0.620000sec

                user     system      total        real
sorting:    0.010000   0.000000   0.010000 (  0.003839)
inject:     0.480000   0.130000   0.610000 (  0.612438)

해시가 항상 단일 키 값 쌍이라고 가정하면 다음이 작동합니다.

a.map {|h| h.to_a[0]}.uniq.map {|k,v| {k => v}}

hash.to_a는 키 값 배열 배열을 만듭니다. 따라서 첫 번째 맵은 다음을 얻습니다.

[[:a, 1], [:a, 2], [:a, 1]]

Uniq On Array는 원하는 것을 수행하여 다음을 제공합니다.

[[:a, 1], [:a, 2]]

그런 다음 두 번째 맵은 다시 해시로 다시 합류합니다.

사용할 수 있습니다 (Ruby 1.9.3에서 테스트),

[{a: 1},{a: 2},{a:1}].uniq => [{a:1},{a: 2}]
[{a: 1,b: 2},{a: 2, b: 2},{a: 1, b: 3}].uniq_by {|v| v[:a]} => [{a: 1,b: 2},{a: 2, b: 2}]

당신이주는 대답은 논의 된 것과 유사합니다. 여기. 그것은 그것을 무시합니다 hash 그리고 eql? 배열에 나타나야하는 해시의 메소드 uniq 올바르게 행동하십시오.

배열의 파이프 메소드 (1.8.6 이후 사용 가능)는 Set Union (배열 반환)을 수행하므로 다음은 모든 배열의 고유 한 요소를 얻을 수있는 또 다른 방법입니다. a:

[] | a

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top