나는 array(1 and 2)
이 있습니다. 어떻게하면 array3
을 얻을 수 있습니까?루비 배열 교차점 (중복 포함)
array1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
array3 = [2,2,2,3,4,8]
array1 & array2
반환 [2,3,4,8]
하지만 나는 중복에 유지해야합니다. 샘플 어레이의 각 요소의 주파수를 얻기
나는 array(1 and 2)
이 있습니다. 어떻게하면 array3
을 얻을 수 있습니까?루비 배열 교차점 (중복 포함)
array1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
array3 = [2,2,2,3,4,8]
array1 & array2
반환 [2,3,4,8]
하지만 나는 중복에 유지해야합니다. 샘플 어레이의 각 요소의 주파수를 얻기
(array1 & array2).flat_map { |n| [n]*[array1.count(n), array2.count(n)].min }
#=> [2,2,2,3,4,8]
단계 :
,515,a = array1 & array2
#=> [2, 3, 4, 8]
a
(2
)의 첫 번째 요소는 블록으로 전달하고, 블록 변수에 할당 : 행한다
n = 2
상기 블록 계산 :
[2]*[array1.count(2), array2.count(2)].min
#=> [2]*[4,3].min
#=> [2]*3
#=> [2,2,2]
너무 2
인 [2,2,2]
에 매핑됩니다. 계산은 a
의 나머지 세 요소에 대해 비슷합니다. flat_map
을 사용하고 있으므로 [2,2,2,3,4,8]
을 반환합니다.
Enumerable#flat_map이 Enumerable#map과 다른 점을 기억하는 데 어려움이 있습니까? flat_map
대신 map
을 사용했다고 가정합니다. 배열 array1
및 array2
이 크고 효율성이 문제가되는 경우
[*[2, 2, 2], *[3], *[4], *[8]]
#=> [2, 2, 2, 3, 4, 8]
, 우리는 조금 할 수 없었다 : 다음
a.map { |n| [n]*[array1.count(n), array2.count(n)].min }
#=> [[2, 2, 2], [3], [4], [8]]
flat_map
그 배열의 각각의 앞에 플랫를 넣어 더 아무것도하지 O의 (N) 전처리 :
def cnt(arr)
arr.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
end
cnt1 = cnt(array1)
#=> {2=>4, 3=>2, 4=>1, 5=>1, 6=>1, 7=>1, 8=>1, 9=>1}
cnt2 = cnt(array2)
#=> {2=>3, 3=>1, 4=>4, 8=>2, 0=>3}
(array1 & array2).flat_map { |n| [n]*[cnt1[n], cnt2[n]].min }
#=> [2,2,2,3,4,8]
array1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
a1, a2 = array1.dup, array2.dup # we’ll mutate them
loop.with_object([]) do |_, memo|
break memo if a1.empty? || a2.empty?
e = a2.delete_at(a2.index(a1.shift)) rescue nil
memo << e if e
end
#⇒ [2,2,2,3,4,8]
array1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
: 그들은 다른 배열 여부에 존재하는 경우
a1_freq=Hash.new(0); a2_freq=Hash.new(0); dup_items=[];
array1.each {|a| a1_freq[a]+=1 }
array2.each {|b| a2_freq[b]+=1 }
마지막 요소를 비교한다. 그렇다면 두 샘플 배열에서 공통 요소의 최소 개수를 가져옵니다.
a1_freq.each {|k,v| a2_freq[k] ? dup_items+=[k]*[v,a2_freq[k]].min : nil}
#dup_items=> [2, 2, 2, 3, 4, 8]
['Hash # default_proc'] (http://ruby-doc.org/core-2.1.5/Hash.html#method-c-new)을 사용해보십시오 :'a1_freq = Hash.new {| h, k | (또는 디폴트 값'a1_freq = Hash.new (0)') 이상한 삼자를 피하십시오 :'array1.each {| a | h [k] = 0}' a1_freq [a] + = 1}'. – mudasobwa
감사합니다. 0으로 초기화 할 수 있다는 것을 알지 못했습니다. – sahil
매우 빠르고 매우 빠릅니다! 게시 한 후에 계산 해시를 만드는 아이디어를 추가했지만 지금까지 솔루션을 놓친 것 같습니다. –
이 조금 장황하지만, 값이 동일한 위치에있는 곳을 의미 가정 : 난 당신이 배열 3에 도착하는 방법을 단서가 없다 난 그냥 지적하고 싶었
def combine(array1, array2)
longer_array = array1.length > array2.length ? array1 : array2
intersection = []
count = 0
longer_array.each do |item|
if array1 == longer_array
looped_array = array2
else
looped_array = array1
end
if item == looped_array[count]
intersection.push(item)
end
count +=1
end
print intersection
end
array_1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array_2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
combine(array_1, array_2)
때문에 세 배열에 대한 인덱스 위치 3 다릅니다
array_1[3] = 2
array_2[3] = 3
array_3[3] = 3
내가 그런 식으로 예상되는 결과에 도달하려고합니다 :
을array1, array2 = [array1, array2].sort_by(&:size)
arr_copy = array2.dup
array1.each.with_object([]) do |el, arr|
index = arr_copy.find_index(el)
arr << arr_copy.slice!(index) if index
end
# => [2, 2, 2, 3, 4, 8]
이것은 재미 있습니다. Cary의 flat_map
솔루션은 특히 영리합니다.여기에 each_with_object
에서 약간의 도움을 정기적으로 오래된 map
를 사용하여 대체 한 줄의 :
#
# we want to duplicate array2 since we'll be
# mutating it to track duplicates
# \ array1 array2
# \ value copy
# \ \ /
array1.each_with_object(array2.dup).map{|v,t| ... }
# | /
# Enumerator for array1 Iterate over
# with a copy of array2 Enumerator with map
: 여기 복잡성의
array1.each_with_object(array2.dup).map{|v,t| v if (l = t.index v) && t.slice!(l) }.compact
#=> [2,2,2,3,4,8]
대부분은 작업을 완료하는 데 충분한 정보 map
를 제공하는 데 사용 인라인 체조를 포함
each_with_object
을 사용하여 array1의 열거자를 제공 할 수 있습니다.이 열은 array2의 복사본에 대한 메서드 체인 액세스를 제공합니다. 그런 다음지도는
each_with_object
열거 자 (array1을 참조)를 반복하여 각 값을 로컬 변수
v
에로드하고 배열 2 복사본을 로컬 변수
t
에로드 할 수 있습니다. 거기에서 :
# map the value IF...
# /it exists in and we were able to
# /our array2 copy remove it from our copy
# / | |
map{|v,t| v if (l = t.index v) && t.slice!(l) }.compact
# | \ \ |
# array1 \ \ dump nils
# value array2 \
# copy load index position into temporary variable l
우리는하는 array1의 각 값을 반복하고 (t
를 통해) 값이 배열 2 내에 존재하는지 여부를 검색합니다. 존재하는 경우 array2의 사본에서 값의 첫 번째 발생을 제거하고 결과 배열의 값을 map
으로 제거합니다.
값이 t
인 array2 사본에 단락 회로 보호로 사용하기 전에 검사를 수행하기 전에 t.slice!(t.index(v))
을 사용하십시오. 우리는 또한 인덱스 값을 로컬 변수 l
에 할당하는 인트 릭 트릭을 사용합니다 : (l = t.index v)
이어서 t.slice!(l)
의 부울 검사에서 l
을 참조 할 수 있습니다.
마지막으로,이 방법론은 array1 값이 array2 내에 존재하지 않을 때마다 nil 값을 매핑하므로 결과가 compact
인 경우 nils가 제거됩니다.
궁금한 점은 지금까지 제시된 해결책에 대한 벤치 마크 테스트입니다. 첫째, 여기에 속도는 샘플 배열의 조작을 10 회 수행 클로킹 :
Cary: 1.050000 0.010000 1.060000 ( 1.061217)
Cary+: 1.580000 0.010000 1.590000 ( 1.603645)
Cam: 0.550000 0.010000 0.560000 ( 0.552062)
Mudasobwa: 2.540000 0.050000 2.590000 ( 2.610395)
Sergii: 0.660000 0.000000 0.660000 ( 0.665408)
Sahil: 1.750000 0.010000 1.760000 ( 1.769624)
#Tommy: 0.290000 0.000000 0.290000 ( 0.290114)
우리가 교차의 높은 수준의 10000 개 정수를 개최 시험 배열을 확장하면 ...
array1 = array2 = []
10000.times{ array1 << rand(10) }
10000.times{ array2 << rand(10) }
루프를 100 번 반복하면 단순 루프 솔루션 (Sahil)이 자체를 구별하기 시작합니다. 캐리의 솔루션은 특히 전처리와, 잘 보유 : 배열 1/10 그러나 1000 개 정수와 교차의 낮은 정도와 크기에
user system total real
Cary: 1.590000 0.020000 1.610000 ( 1.615798)
Cary+: 0.870000 0.010000 0.880000 ( 0.879331)
Cam: 6.680000 0.090000 6.770000 ( 6.838829)
Mudasobwa: 6.740000 0.080000 6.820000 ( 6.898394)
Sergii: 6.760000 0.100000 6.860000 ( 6.962025)
Sahil: 0.740000 0.030000 0.770000 ( 0.785975)
#Tommy: 0.430000 0.010000 0.440000 ( 0.446482)
...
array1 = array2 = []
1000.times{ array1 << rand(10000) }
1000.times{ array2 << rand(10000) }
우리를 루프 10 배의 flat_map 솔루션은 ... 평평하게됩니다 우리가 (캐리 +) 전처리를 사용하는 경우를 제외하고 다음은
user system total real
Cary: 135.400000 0.700000 136.100000 (137.123393)
Cary+: 0.270000 0.010000 0.280000 ( 0.268255)
Cam: 0.670000 0.000000 0.670000 ( 0.676438)
Mudasobwa: 0.670000 0.010000 0.680000 ( 0.684088)
Sergii: 0.660000 0.010000 0.670000 ( 0.673881)
Sahil: 1.970000 2.130000 4.100000 ( 4.121759)
#Tommy: 0.050000 0.000000 0.050000 ( 0.045970)
는 벤치 마크와 요점이다 : https://gist.github.com/camerican/139463b4bd9e0fd89424377931042ce4
재미있는 솔루션과 비교, 그리고 훌륭한 프레 젠 테이션. 이것에 대한 당신의 모든 노력에 찬사를 보냅니다. 내 솔루션의 변형을 "전처리"와 함께 벤치 마크에 추가 할 수 있습니까? –
'Cary +'에서 flat_map w/preprocessing을 포함하도록 테스트가 업데이트되었습니다. 여분의 오버 헤드는 100,000x 테스트에서 불이익을 받지만 큰 어레이에서는 많은 도움이됩니다. 나는 테스트와 요지를 연결했다. – Cam
@ Tommyixi는 그의 Wheaties를 먹고 있습니다. –
중복으로 두 배열의 같은 위치에있는 값을 의미합니까? – sahil
나는'array3'에 3이 들어 있기 때문에 그가하지 않는다고 생각하지만, 값은'array1'과'array2'에 정렬되어 있지 않습니다. –
결과의 요소 순서가 중요한지 여부와 최소 또는 최대 일치 개수가 필요한지, 즉 배열 비교 순서가 중요한지 여부를 지정해야합니다. –