Ruby의 오브젝트 속성 별 Uniq
하나 이상의 속성과 관련하여 고유 한 배열에서 객체를 선택하는 가장 우아한 방법은 무엇입니까?
이러한 객체는 ActiveRecord에 저장되므로 AR의 방법을 사용하는 것도 좋습니다.
Array#uniq
블록과 함께 사용 :
@photos = @photos.uniq { |p| p.album_id }
uniq_by
프로젝트의 배열에 메소드를 추가하십시오 . 와 유추하여 작동합니다 sort_by
. 그래서 uniq_by
이다 uniq
대로 sort_by
에있다 sort
. 용법:
uniq_array = my_array.uniq_by {|obj| obj.id}
구현 :
class Array
def uniq_by(&blk)
transforms = []
self.select do |el|
should_keep = !transforms.include?(t=blk[el])
transforms << t
should_keep
end
end
end
현재 배열을 수정하지 않고 새 배열을 반환합니다. 우리는 uniq_by!
방법을 작성하지 않았지만 원한다면 충분히 쉬울 것입니다.
편집 : 부족의 느낌은 그 구현이 O (n ^ 2)라고 지적합니다. 더 나은 (예상치 않은) 것입니다 ...
class Array
def uniq_by(&blk)
transforms = {}
select do |el|
t = blk[el]
should_keep = !transforms[t]
transforms[t] = true
should_keep
end
end
end
데이터베이스 레벨에서 수행하십시오.
YourModel.find(:all, :group => "status")
이 트릭을 사용하여 배열에서 여러 속성 요소로 고유 한 것을 선택할 수 있습니다.
@photos = @photos.uniq { |p| [p.album_id, p.author_id] }
원래 select
Array 의 메소드 사용을 제안했습니다 . 재치 :
[1, 2, 3, 4, 5, 6, 7].select{|e| e%2 == 0}
우리를 [2,4,6]
돌려줍니다.
그러나 첫 번째 객체를 원하면을 사용하십시오 detect
.
[1, 2, 3, 4, 5, 6, 7].detect{|e| e>3}
우리를 제공합니다 4
.
그래도 당신이 여기서 무엇을할지 모르겠습니다.
나는 jmah가 고유성을 강화하기 위해 해시를 사용하는 것을 좋아합니다. 고양이에게 피부를 바르는 방법이 몇 가지 더 있습니다 :
objs.inject({}) {|h,e| h[e.attr]=e; h}.values
1- 라이너는 좋지만 조금 더 빠를 것 같습니다.
h = {}
objs.each {|e| h[e.attr]=e}
h.values
귀하의 질문을 올바르게 이해하면 Marshaled 객체를 비교하여 속성이 다른지 결정하는 유사 해킹 방식을 사용 하여이 문제를 해결했습니다. 다음 코드의 끝에 주입하는 것이 예입니다.
class Foo
attr_accessor :foo, :bar, :baz
def initialize(foo,bar,baz)
@foo = foo
@bar = bar
@baz = baz
end
end
objs = [Foo.new(1,2,3),Foo.new(1,2,3),Foo.new(2,3,4)]
# find objects that are uniq with respect to attributes
objs.inject([]) do |uniqs,obj|
if uniqs.all? { |e| Marshal.dump(e) != Marshal.dump(obj) }
uniqs << obj
end
uniqs
end
내가 찾은 가장 우아한 방법 Array#uniq
은 블록을 사용한 스핀 오프 입니다.
enumerable_collection.uniq(&:property)
…it reads better too!
You can use a hash, which contains only one value for each key:
Hash[*recs.map{|ar| [ar[attr],ar]}.flatten].values
Rails also has a #uniq_by method - see Parameterized Array#uniq (i.e., uniq_by)
I like jmah and Head's answers. But do they preserve array order? They might in later versions of ruby since there have been some hash insertion-order-preserving requirements written into the language specification, but here's a similar solution that I like to use that preserves order regardless.
h = Set.new
objs.select{|el| h.add?(el.attr)}
ActiveSupport implementation:
def uniq_by
hash, array = {}, []
each { |i| hash[yield(i)] ||= (array << i) }
array
end
Now if you can sort on the attribute values this can be done:
class A
attr_accessor :val
def initialize(v); self.val = v; end
end
objs = [1,2,6,3,7,7,8,2,8].map{|i| A.new(i)}
objs.sort_by{|a| a.val}.inject([]) do |uniqs, a|
uniqs << a if uniqs.empty? || a.val != uniqs.last.val
uniqs
end
That's for a 1-attribute unique, but the same thing can be done w/ lexicographical sort ...
Use Array#uniq with a block:
objects.uniq {|obj| obj.attribute}
Or a more concise approach:
objects.uniq(&:attribute)
참고URL : https://stackoverflow.com/questions/109781/uniq-by-object-attribute-in-ruby
'Programming' 카테고리의 다른 글
Visual Studio 2013 Preview를 끄려면 어떻게해야합니까? (0) | 2020.07.19 |
---|---|
모든 경로에 대해 index.html을 제공하도록 webpack dev 서버에 지시하는 방법 (0) | 2020.07.19 |
파이썬에서 매우 많은 수의 처리 (0) | 2020.07.19 |
파이썬 dict.update ()가 객체를 반환하지 않는 이유는 무엇입니까? (0) | 2020.07.19 |
CSS를 사용하여 테이블의 두 번째 열만 변경하는 방법 (0) | 2020.07.19 |