arr = [1,2,1,3,5,2,4]
Comment puis-je compter le tableau par valeur de groupe avec tri ? J'ai besoin de la sortie suivante :
x[1] = 2
x[2] = 2
x[3] = 1
x[4] = 1
x[5] = 1
arr = [1,2,1,3,5,2,4]
Comment puis-je compter le tableau par valeur de groupe avec tri ? J'ai besoin de la sortie suivante :
x[1] = 2
x[2] = 2
x[3] = 1
x[4] = 1
x[5] = 1
Disponible uniquement sous ruby 1.9
En gros, c'est la même chose que Réponse de Michael mais de façon un peu plus courte :
x = arr.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
Dans des situations similaires,
Array
, Hash
, String
vous pouvez utiliser each_with_object
comme dans le cas ci-dessus.Lorsque l'élément de départ est un immuable tel que Numeric
vous devez utiliser inject
comme ci-dessous.
sum = (1..10).inject(0) {|sum, n| sum + n} # => 55
Il existe une version courte qui se trouve dans ruby 2.7 => Enumerable#tally
.
[1,2,1,3,5,2,4].tally #=> { 1=>2, 2=>2, 3=>1, 5=>1, 4=>1 }
# Other possible usage
(1..6).tally { |i| i%3 } #=> { 0=>2, 1=>2, 2=>2 }
Encore une autre approche - semblable à d'autres :
result=Hash[arr.group_by{|x|x}.map{|k,v| [k,v.size]}]
result[1]=2 ...
.Chaque fois que vous trouvez quelqu'un qui affirme que quelque chose est le plus rapide sur ce type de routine primitive, je trouve toujours intéressant de le confirmer, car sans confirmation, la plupart d'entre nous ne font que deviner. Donc j'ai pris toutes les méthodes ici et je les ai comparées.
J'ai pris un tableau de 120 liens que j'ai extraits d'une page Web et que je devais regrouper par nombre. J'ai mis en œuvre tous ces éléments en utilisant une boucle seconds = Benchmark.realtime et j'ai obtenu tous les temps.
Supposons que links soit le nom du tableau que je dois compter :
#0.00077
seconds = Benchmark.realtime do
counted_links = {}
links.each { |e| counted_links[e] = links.count(e) if counted_links[e].nil?}
end
seconds
#0.000232
seconds = Benchmark.realtime do
counted_links = {}
links.sort.group_by {|x|x}.each{|x,y| counted_links[x] = y.size}
end
#0.00076
seconds = Benchmark.realtime do
Hash[links.uniq.map{ |i| [i, links.count(i)] }]
end
#0.000107
seconds = Benchmark.realtime do
links.inject(Hash.new(0)) {|h, v| h[v] += 1; h}
end
#0.000109
seconds = Benchmark.realtime do
links.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
end
#0.000143
seconds = Benchmark.realtime do
links.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
end
Et ensuite un peu de ruby pour trouver la réponse :
times = [0.00077, 0.000232, 0.00076, 0.000107, 0.000109, 0.000143].min
==> 0.000107
Donc la méthode la plus rapide, selon vous bien sûr, est :
links.inject(Hash.new(0)) {|h, v| h[v] += 1; h}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.