2016-07-15 14 views
2

Ich hatte eine Funktion in R (onestep unten), die als Argument einen Vektor v nahm und einen neuen Vektor v als Ausgabe, die eine Funktion des Eingabevektors war. I iteriert dann diese Funktion niter Zeiten und hielt die Ausgangsvektoren jeder Iteration (die die gleiche Länge haben nicht alle sind und 0 Länge am Ende mit gelegentlich auch kann) in einer anderen Funktion iterate wie folgt (minimal Beispiel):Julia - Äquivalent der rekursiven Sapply-Funktion in R

onestep = function (v) c(v,2*v) 
iterate = function (v, niter) sapply(1:niter, function (iter) {v <<- onestep(v) 
                   return(v) }) 

Beispiel:

v=c(1,2,3) 
iterate(v,3) 

[[1]] 
[1] 1 2 3 2 4 6 

[[2]] 
[1] 1 2 3 2 4 6 2 4 6 4 8 12 

[[3]] 
[1] 1 2 3 2 4 6 2 4 6 4 8 12 2 4 6 4 8 12 4 8 12 8 16 24 

ich habe mich gefragt, was eine kompakte und idiomatische Weg wäre, eine solche rekursive Funktion zu tun, die alle Zwischenergebnisse in Julia zurückkehrt? Irgendwelche Gedanken? (Entschuldigt, wenn dies trivial ist, aber ich bin neu in Julia)

Antwort

3

Nicht sicher auf dem kompakten und idiomatische vorne, aber das ist, wie ich es tun würde

onestep(v) = [v 2*v] 

function iterate(v, niter) 
    Results = Array(Array, niter) 
    Results[1] = onestep(v) 
    for idx = 2:niter 
     Results[idx] = onestep(Results[idx - 1]) 
    end 
    Results 
end 

v = [1 2 3] 
iterate(v, 3) 
+0

Vielen Dank - das ist perfekt für mich! Das Sapply mit v als globale Variable war sowieso ein bisschen zwielichtig :-) Vielen Dank für Ihre freundliche Hilfe! –

+0

@TomWenseleers Sicher Sache. Wenn Sie von R nach Julia wechseln, werden Sie im Allgemeinen feststellen, dass Sie viele Dinge auf der Basis von Schleifen aller Arten machen, was im Allgemeinen schneller ist als die Vektorisierung. So werden Dinge wie "Sapply" in vielen Fällen nicht so sehr in Ihren Kopf kommen. Wenn Sie Performance suchen und aus einem R-Hintergrund kommen, empfehle ich Ihnen, die Julia-Performance-Guides zu lesen und dabei besonders auf das Casting in Ihren Funktionen zu achten (was ich hier zur Vereinfachung der Darstellung nicht getan habe). –

2

ist hier eine andere Art und Weise, die ein bisschen mehr concise und wirklich rekursiv, wie pro Ihre ursprüngliche Frage:

v = Array[[1, 2, 3]] ## create v as an array of one dimensional arrays 
function iterate(v::Array{Array, 1}, niter::Int) 
    niter == 0 && return v[2:end] 
    push!(v, [v[end] ; 2v[end]]) 
    niter -= 1 
    iterate(v, niter) 
end 

iterate(v, 3) 
+0

Danke dafür, +1 - obwohl ich denke, dass ich deine andere Lösung immer noch mehr in Bezug auf Lesbarkeit bevorzuge. Mein letztes kleines Julia-Programm ist hier, http://codereview.stackexchange.com/questions/134926/simulating-evolution-of-a-trait-in-a-asexual-population, falls Sie den Weg kommentieren möchten Ich habe es codiert, oder wenn Sie irgendwelche offensichtlichen Möglichkeiten sehen würden, die Leistung zu steigern ... –

+0

@TomWenseleers Ja, ich bin bei Ihnen auf der Lesbarkeit und habe einfachen, intuitiven Code, anstatt zu versuchen, die idiomatischen und prägnanten Wege zu finden Dinge jedes Mal. Ich kodiere in vielen Sprachen und bevorzuge daher Lösungen, die auf der Implementierung einiger einfacher und universeller Codierungsgrundsätze basieren. –