To jest zabawne; Rozwiązanie Cary'ego flat_map
jest szczególnie sprytne.Oto alternatywa jedno-liner stosując regularne stare map
z jakiejś pomocy od each_with_object
:
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]
Wiele złożoności tutaj polega inline gimnastyka wykorzystywane w celu zapewnienia map
wystarczających informacji, aby wykonać zadanie:
#
# 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
Możemy użyć each_with_object
, aby dostarczyć moduł wyliczający dla tablicy 1, który również daje naszemu łańcuchowi metod dostęp do kopii tablicy2. Mapę można następnie przetestować na module wyliczającym each_with_object
(który odwołuje się do array1), ładując każdą wartość do zmiennej lokalnej v
i naszej kopii array2 do zmiennej lokalnej t
. Stamtąd:
# 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
Mamy iteracyjne nad każdej wartości tablica1 i sprawdzić, czy wartość istnieje w tablica2 (przez t
). Jeśli istnieje, usuniemy pierwsze wystąpienie wartości z naszej kopii array2 i map
wartość naszej wynikowej tablicy.
Uwaga: kontrola t.index(v)
przed t.slice!(t.index(v))
jest używana jako zabezpieczenie przed zwarciem w przypadku, gdy wartość nie istnieje w ramach t
, naszej kopii tablicy2. Korzystamy również z inkrementacji polegającej na przypisywaniu wartości indeksu do lokalnej zmiennej l
tutaj: (l = t.index v)
, abyśmy mogli odnieść się do l
w kolejnej kontroli boolowskiej: t.slice!(l)
.
Wreszcie, ponieważ ta metodologia będzie mapować wartości zerowe, gdy wartość tablicy1 nie istnieje w tablicy2, my compact
wynik, aby usunąć nils.
Dla ciekawskich, oto kilka testów porównawczych prezentowanych rozwiązań. Po pierwsze, tutaj są szybkości wykonywania operacji taktowany 100.000 razy na tablicach przykładowych:
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)
Jeśli rozszerzymy tablice testowe trzymać 10000 liczb całkowitych z wysokim stopniem skrzyżowaniu ...
array1 = array2 = []
10000.times{ array1 << rand(10) }
10000.times{ array2 << rand(10) }
i pętla 100 razy, proste rozwiązanie pętli (Sahil) zaczyna się rozróżniać. Rozwiązanie Cary trzyma też się dobrze, zwłaszcza z wyprzedzającym:
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)
Na tablicach 1/10th wielkości z 1000 liczb całkowitych i niskim stopniu skrzyżowaniu jednak ...
array1 = array2 = []
1000.times{ array1 << rand(10000) }
1000.times{ array2 << rand(10000) }
kiedy pętla 10 razy, rozwiązanie flat_map zostaje spłaszczona ... z wyjątkiem jeśli używamy przerób (Cary +):
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)
Oto istota z benchmarków: https://gist.github.com/camerican/139463b4bd9e0fd89424377931042ce4
Przez duplikat masz na myśli wartości w tej samej pozycji w obu tablicach? – sahil
Myślę, że nie, ponieważ istnieje 3 w "array3", ale wartości nie są wyrównane w 'tablica1' i' tablica2'. –
Należy określić, czy kolejność elementów w wyniku jest ważna i czy wymagana jest minimalna lub maksymalna liczba dopasowań, to znaczy, czy kolejność porównywania tablic jest ważna. –