2012-01-04 2 views
1

내 모델 중 하나에서 직렬화 된 배열 필드, 특히 각 배열의 멤버 수를 계산하는 작업을하고 있습니다.Ruby Array - 중복을 빠르게 계산하는 방법

내 프로젝트의 성격 상 이러한 중복 카운트 횟수가 너무 많습니다. 이렇게하려면이 작업을 수행 할 수있는 빠르고 손쉬운 방법이 있는지 궁금합니다. 순간

, 내 코드는 잘 작동이

(user1.follower_names & user2.follower_names).count 

처럼 보이는, 그래서 나는 '&'방법을 사용하고 있습니다 ...하지만 난 그것을 할 수있는 빠른 방법이 될 수있을 기대했다.

+0

정확한 Ruby는 없지만 Python에는 기본 제공 Set가 있습니다. 모든 추종자를 추가 한 다음 그 길이/수를 잡아 당길 수 있습니다. 다른 사람들은 루비 - 방법을 알지도 모르고 어떤 종류의 성능을 기대할 수 있습니다. –

답변

4

세트가 더 빠릅니다.

require 'benchmark' 
require 'set' 
alphabet = ('a'..'z').to_a 
user1_followers = 100.times.map{ alphabet.sample(3) } 
user2_followers = 100.times.map{ alphabet.sample(3) } 
user1_followers_set = user1_followers.to_set 
user2_followers_set = user2_followers.to_set 

n = 1000 
Benchmark.bm(7) do |x| 
    x.report('arrays'){ n.times{ (user1_followers & user2_followers).size } } 
    x.report('set'){ n.times{ (user1_followers_set & user2_followers_set).size } } 
end 

출력 :

   user  system  total  real 
arrays 0.910000 0.000000 0.910000 ( 0.926098) 
set  0.350000 0.000000 0.350000 ( 0.359571) 
+0

배열을 배열로 바꾸는 데 걸리는 시간이 조금 걱정 스럽습니다. 무시할 수 있을까요? 내 배열의 길이는 0-3000입니다. – BananaNeil

+0

아니오, 무시할 수 없습니다. 실제 교차 작업과 함께 1000 번 설정하는 두 전환은이 골동품 랩톱에서 약 1 초가 걸립니다. 그러나 user_follower가 여러 팔로어와 비교되는 시나리오에서는 세트를 메모리에 저장하고 팔로어 수가 1보다 큰 경우 시간이 절약되기 시작합니다. 즉, 두 번 변환하지 마십시오. – steenslag

+0

그냥 몇개의 숫자를 달았습니다 ... 세트를 사용하는 것이 실제로 느린 것 같습니다. 세트로의 변환이 너무 오래 걸렸기 때문입니다. 나는 모든 데이터 구조를 직렬화 된 세트로 변경할 수 있다고 생각하는데, 어느 시점에서 훨씬 더 빠를 것입니다. – BananaNeil

1
위의 대안은 사용하는 것입니다

'-'배열에 대한 연산자

user1.follower_names.size - (user1.follower_names - user2.follower_names).size 

기본적으로이 목록에 하나의 크기가 도착을하고 적자 교차점이없는 공동 목록의 크기 이것은 집합을 사용하는 것만 큼 빠르지는 않지만 배열과의 교집합을 사용하는 것보다 훨씬 빠릅니다.

+0

그것은 매우 빠르고 (약 1/100000 초) 더 빨랐지만 몇 번이나 실행해도 조금 빠릅니다. 그래서 나는 당신에게 상향 투표를했습니다.] – BananaNeil