2016-06-18 20 views
5

Niech x::Vector{Vector{T}}. Jaki jest najlepszy sposób na powtórzenie wszystkich elementów każdego wektora wewnętrznego (tj. Wszystkich elementów typu T)? Najlepsze, co mogę wymyślić jest podwójne iteracji za pomocą notacji pojedynczej linii, tj:Jaki jest najprostszy sposób na iterację w tablicy tablic?

for n in eachindex(x), m in eachindex(x[n]) 
    x[n][m] 
end 

ale zastanawiam się, czy istnieje pojedynczy iterator, może w pakiecie Iterators, zaprojektowany specjalnie do tego celu np for i in some_iterator(x) ; x[i] ; end.

Bardziej ogólnie, co z iterowaniem ponad najbardziej wewnętrznymi elementami dowolnej tablicy tablic (czyli tablic dowolnego wymiaru)?

+1

Używanie pakietu Iterator: 'dla m w łańcuchu (x ...) println (m); koniec'. Powinien być również skuteczny. –

+0

@ DanGetz Ah, to jest miłe! Wielkie dzięki. –

Odpowiedz

7

Twój sposób

for n in eachindex(x), m in eachindex(x[n]) 
    x[n][m] 
end 

jest dość szybki. Jeśli chcesz najlepszą prędkość, użyj

for n in eachindex(x) 
    y = x[n] 
    for m in eachindex(y) 
     y[m] 
    end 
end 

który unika dereferencing dwukrotnie (pierwszy dereference trudno zoptymalizować, bo tablice są zmienne, a więc getindex nie jest czysta). Ewentualnie, jeśli nie trzeba m i n, można po prostu użyć

for y in x, for z in y 
    z 
end 

który jest również szybki.

Pamiętaj, że przechowywanie w kolumnie głównej jest nieistotne, ponieważ wszystkie tablice są tutaj jednowymiarowe.

Aby odpowiedzieć na to pytanie ogólne:

  • Jeśli liczba wymiarów jest kompilacji stałą czasową, patrz Base.Cartesian
  • Jeśli liczba wymiarów nie jest kompilacji stała, stosowanie rekurencji

I wreszcie, jak Dan Getz wspomniano w komentarzu:

using Iterators 
for z in chain(x...) 
    z 
end 

również działa. Ma to jednak niewielki wpływ na wydajność.

+0

Kiedy mówisz, że 'getindex' nie jest czysty - czy możesz podać nieco więcej wyjaśnień, co to oznacza? Dzięki! –

+0

Dzięki za odpowiedź - dowiedziałem się kilku nowych rzeczy z tej odpowiedzi. @DanGetz miał fajne podejście także w komentarzach do pytania, które możesz chcieć włączyć do odpowiedzi. Twoje zdrowie. –

+3

@aireties A [funkcja czysta] (https://en.wikipedia.org/wiki/Pure_function) to funkcja, która zawsze zwraca ten sam wynik dla tego samego wejścia i nie ma żadnych skutków ubocznych. Na przykład '+' na liczbach jest czyste, ponieważ '1 + 1' będzie zawsze" 2 ". Jeśli kompilator może wykryć, że funkcja jest czysta, może uniknąć wielokrotnego jej obliczania. Niestety, 'getindex' nie jest czysty, ponieważ' A [1] 'może oznaczać coś innego, jeśli' A' został zmutowany. Bardzo trudno jest kompilatorowi zrozumieć, że 'x [n]' nie musi być obliczane za każdym razem. –

Powiązane problemy