2016-09-22 1 views
4

Ich habe ein Array mit +20000 Integer-Elementen.Effiziente Weise, Zusatz auf großem Array zu tun

Ich möchte ein neues Array erstellen, bei dem jedem Element im alten Array eine Änderungsnummer hinzugefügt wird. Auf einem kleinen Beispiel-Array würde es so aussehen:

old_array = [2,5,6,8] 
modifying_number = 3 
new_array = [5,8,9,11] 

Gibt es einen effizienteren Weg als eine Iteration wie diese?

+1

scheint der Kern 'map' den Tag gewinnt. Die Frage scheint nun nun zu sein, welche Implementierung von Ruby die schnellste 'Karte' hat? –

Antwort

3

Nr. N Iterationen sind die minimale Komplexität dieses Algorithmus.

Sie können es an Ort und Stelle tun, indem Sie Quell-Array mit collect! ändern (wenn Sie aus irgendeinem Grund kein Quell-Array benötigen). Die Komplexität ist gleich, zusätzliches großes Objekt wird nicht erstellt.

+0

gut bearbeiten über vor Ort Änderung;) –

3

20k Datensätze ist nicht viel über die Leistung zu kümmern.

ary = Array.new(20000) { 1 } 
ary.map! { |el| el + 1 } 

würde ganz gut funktionieren.

Ich würde nur vorschlagen, das ursprüngliche Array inplace zu ändern, anstatt ein neues zu erstellen (mit Methode mit bang), so wird es definitiv weniger Ressourcen verwenden.

2

Ich denke, es würde bedeuten, map auf andere Weise zu implementieren? This question beschäftigt sich mit einer solchen Aufgabe. Ich habe Benchmarks der Antworten von @ JörgWMittag und @uishra aufgenommen. Obwohl es gesagt werden muss speed war keine Anforderung in der verknüpften Frage, so dass die Antworten in dieser Hinsicht nicht kritisiert werden können. Ich habe auch @ CarySwovelands Antwort von dieser Frage eingeschlossen.

require 'fruity' 
require 'matrix' 

class Array 
    #jörg_w_mittag 
    def new_map 
    return enum_for(__callee__) unless block_given? 
    inject([]) {|acc, el| acc << yield(el) } 
    end 

    #uishra 
    def my_map(&block) 
    result = [] 
    each do |element| 
    result << block.call(element) 
    end 
    result 
    end 

    #cary_swoveland 
    def vec_map(k) 
    (Vector[*[k]*self.size] + Vector[*self]).to_a 
    end 

end 

arr = (1..30000).to_a 
k = 3 

10.times do 
    compare do 
    core_map  { ar = arr.dup; ar.map  { |n| n + k } } 
    jörg_w_mittag { ar = arr.dup; ar.new_map { |n| n + k } } 
    uishra   { ar = arr.dup; ar.my_map { |n| n + k } } 
    cary_swoveland { ar = arr.dup; ar.vec_map k } 
    end 
    puts 
end 

Eine Zusammenfassung der Ergebnisse/Ausgabe:

Ergebnisse bei fünf Gelegenheiten

#Running each test once. Test will take about 1 second. 
#core_map is faster than jörg_w_mittag by 2x ± 1.0 
#jörg_w_mittag is similar to uishra 
#uishra is similar to cary_swoveland 

Ergebnisse bei zwei Gelegenheiten

#Running each test once. Test will take about 1 second. 
#core_map is faster than jörg_w_mittag by 2x ± 0.1 
#jörg_w_mittag is similar to uishra 
#uishra is similar to cary_swoveland 

Ergebnisse bei drei Gelegenheiten

#Running each test once. Test will take about 1 second. 
#core_map is faster than uishra by 2x ± 1.0 
#uishra is similar to jörg_w_mittag 
#jörg_w_mittag is similar to cary_swoveland 
+0

Sagar, können Sie meine Methode zu Ihrem Benchmark hinzufügen? Ich tat es und es war für den Rest gebunden. Übrigens habe ich den Benchmark mehrmals durchlaufen. Manchmal war Ushra schneller als Jörg_W_Mittag, manchmal nicht. Warte eine Minute. Wo ist Jörgs Antwort? –

+0

@CarySwoveland er Benchmarks Antworten aus der [verknüpften Frage] (http://StackOverflow.com/Questions/39609277/Create-On-ArrayMap-Like-Method) :) –

+0

@CarySwoveland Ich habe die Benchmarks aktualisiert. Meine ursprüngliche Antwort (wie diese Antwort) enthielt Jörgs Antwort, aber ich hatte gerade seinen Methodennamen leicht geändert, aber die Implementierung war die gleiche. Wenn Sie das Gefühl haben, dass ich meine Antwort verbessern muss, lassen Sie es mich wissen. Und nebenbei habe ich 'fruchtig.rb' aus einer deiner früheren SO Antworten entdeckt, also ta für das! –

1
require 'matrix' 

class Array 
    def vec_map(k) 
    (Vector[*[k]*self.size] + Vector[*self]).to_a 
    end 
end 

[1,2,3].vec_map 4 
    #=> [5, 6, 7] 
Verwandte Themen