Saya punya masalah. Saya perlu mengulang melalui setiap elemen dalam matriks n-dimensi di MATLAB. Masalahnya adalah, saya tidak tahu bagaimana melakukan ini untuk jumlah dimensi yang berubah-ubah. Saya tahu saya bisa mengatakannya
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
dan seterusnya, tetapi apakah ada cara untuk melakukannya untuk jumlah dimensi yang berubah-ubah?
Jawaban:
Anda dapat menggunakan pengindeksan linier untuk mengakses setiap elemen.
for idx = 1:numel(array) element = array(idx) .... end
Ini berguna jika Anda tidak perlu tahu apa i, j, k, Anda. Namun, jika Anda tidak perlu mengetahui indeks Anda, Anda mungkin lebih baik menggunakan arrayfun ()
sumber
I = cell(1, ndims(array)); [I{:}] = ind2sub(size(array),idx);
.Ide indeks linier untuk array di matlab adalah satu hal yang penting. Array dalam MATLAB sebenarnya hanyalah sebuah vektor elemen, dirangkai dalam memori. MATLAB memungkinkan Anda menggunakan indeks baris dan kolom, atau indeks linier tunggal. Sebagai contoh,
A = magic(3) A = 8 1 6 3 5 7 4 9 2 A(2,3) ans = 7 A(8) ans = 7
Kita dapat melihat urutan elemen disimpan dalam memori dengan membuka gulungan array menjadi vektor.
A(:) ans = 8 3 4 1 5 9 6 7 2
Seperti yang Anda lihat, elemen ke-8 adalah angka 7. Faktanya, fungsi find mengembalikan hasilnya sebagai indeks linier.
find(A>6) ans = 1 6 8
Hasilnya adalah, kita dapat mengakses setiap elemen secara bergiliran dari array nd umum menggunakan satu loop. Misalnya, jika kita ingin mengkuadratkan elemen A (ya, saya tahu ada cara yang lebih baik untuk melakukan ini), seseorang dapat melakukan ini:
B = zeros(size(A)); for i = 1:numel(A) B(i) = A(i).^2; end B B = 64 1 36 9 25 49 16 81 4
Ada banyak situasi di mana indeks linier lebih berguna. Konversi antara indeks linier dan dua (atau lebih tinggi) dimensi subskrip dilakukan dengan fungsi sub2ind dan ind2sub.
Indeks linier berlaku secara umum untuk semua larik di matlab. Jadi Anda bisa menggunakannya pada struktur, array sel, dll. Satu-satunya masalah dengan indeks linier adalah ketika indeks terlalu besar. MATLAB menggunakan integer 32 bit untuk menyimpan indeks ini. Jadi jika array Anda memiliki lebih dari total 2 ^ 32 elemen di dalamnya, indeks linier akan gagal. Ini benar-benar hanya menjadi masalah jika Anda sering menggunakan matriks renggang, padahal terkadang hal ini akan menyebabkan masalah. (Meskipun saya tidak menggunakan rilis MATLAB 64 bit, saya percaya bahwa masalah tersebut telah diselesaikan untuk orang-orang yang beruntung yang melakukannya.)
sumber
x = ones(1,2^33,'uint8'); x(2^33)
berfungsi seperti yang diharapkan.Seperti yang ditunjukkan dalam beberapa jawaban lain, Anda dapat mengulang semua elemen dalam matriks
A
(dari dimensi apa pun) menggunakan indeks linier dari1
kenumel(A)
dalam satu perulangan for. Ada juga beberapa fungsi yang dapat Anda gunakan:arrayfun
dancellfun
.Mari kita asumsikan pertama Anda memiliki fungsi yang ingin Anda terapkan ke setiap elemen
A
(dipanggilmy_func
). Anda pertama kali membuat tuas fungsi untuk fungsi ini:Jika
A
merupakan matriks (tipe double, single, dll.) Dengan dimensi arbitrer, Anda dapat menggunakanarrayfun
untuk diterapkanmy_func
ke setiap elemen:Jika
A
adalah larik sel dengan dimensi arbitrer, Anda dapat menggunakancellfun
untuk diterapkanmy_func
ke setiap sel:outArgs = cellfun(fcn, A);
Fungsi
my_func
tersebut harus menerimaA
sebagai masukan. Jika ada keluaran darimy_func
, ini ditempatkan dioutArgs
, yang akan memiliki ukuran / dimensi yang sama sepertiA
.Satu peringatan pada output ... jika
my_func
mengembalikan output dengan ukuran dan tipe berbeda ketika beroperasi pada elemen yang berbedaA
, makaoutArgs
harus dibuat menjadi array sel. Ini dilakukan dengan memanggil salah satuarrayfun
ataucellfun
dengan pasangan parameter / nilai tambahan:outArgs = arrayfun(fcn, A, 'UniformOutput', false); outArgs = cellfun(fcn, A, 'UniformOutput', false);
sumber
Trik lainnya adalah menggunakan
ind2sub
dansub2ind
. Dalam hubungannya dengannumel
dansize
, ini memungkinkan Anda melakukan hal-hal seperti berikut, yang membuat larik berdimensi-N, dan kemudian menyetel semua elemen pada "diagonal" menjadi 1.d = zeros( 3, 4, 5, 6 ); % Let's pretend this is a user input nel = numel( d ); sz = size( d ); szargs = cell( 1, ndims( d ) ); % We'll use this with ind2sub in the loop for ii=1:nel [ szargs{:} ] = ind2sub( sz, ii ); % Convert linear index back to subscripts if all( [szargs{2:end}] == szargs{1} ) % On the diagonal? d( ii ) = 1; end end
sumber
Anda bisa membuat fungsi rekursif bekerja
L = size(M)
idx = zeros(L,1)
length(L)
sebagai kedalaman maksimalfor idx(depth) = 1:L(depth)
length(L)
, lakukan operasi elemen, jika tidak, panggil fungsi lagi dengandepth+1
Tidak secepat metode vektor jika Anda ingin memeriksa semua poin, tetapi jika Anda tidak perlu mengevaluasi sebagian besar dari mereka, ini bisa menghemat waktu.
sumber
solusi ini lebih cepat (sekitar 11%) daripada menggunakan
numel
;)for idx = reshape(array,1,[]), element = element + idx; end
atau
for idx = array(:)', element = element + idx; end
UPD. tnx @rayryeng untuk kesalahan yang terdeteksi dalam jawaban terakhir
Penolakan
Informasi waktu yang dirujuk posting ini salah dan tidak akurat karena kesalahan ketik mendasar yang dibuat (lihat aliran komentar di bawah serta riwayat edit - secara khusus lihat versi pertama dari jawaban ini). Caveat Emptor .
sumber
1 : array(:)
setara dengan1 : array(1)
. Ini tidak mengulangi semua elemen, itulah sebabnya waktu kerja Anda cepat. Selain itu,rand
menghasilkan angka floating-point , dan hal itu1 : array(:)
akan menghasilkan larik kosong karena pernyataan Anda mencoba menemukan vektor yang meningkat dengan nilai awalnya sebagai 1 dengan nilai akhir sebagai angka floating-point dengan kisaran[0,1)
eksklusif 1 dalam peningkatan langkah-langkah 1. Tidak ada vektor yang memungkinkan, yang menghasilkan vektor kosong. Andafor
loop tidak dijalankan, sehingga klaim Anda adalah palsu. -1 suara. Maaf.reshape(...)
.1 : array(:)
di command prompt Anda setelah membuatarray
. Apakah Anda mendapatkan matriks kosong? jika ya maka kode Anda tidak berfungsi. Saya meninggalkan suara saya karena Anda memberikan informasi palsu.Jika Anda melihat lebih dalam kegunaan lain dari
size
Anda dapat melihat bahwa Anda sebenarnya bisa mendapatkan vektor ukuran setiap dimensi. Tautan ini menunjukkan dokumentasi kepada Anda:www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html
Setelah mendapatkan vektor ukuran, lakukan iterasi pada vektor tersebut. Sesuatu seperti ini (maafkan sintaks saya karena saya tidak menggunakan Matlab sejak kuliah):
d = size(m); dims = ndims(m); for dimNumber = 1:dims for i = 1:d[dimNumber] ...
Jadikan ini menjadi sintaks Matlab-legal yang sebenarnya, dan saya pikir itu akan melakukan apa yang Anda inginkan.
Selain itu, Anda harus dapat melakukan Pengindeksan Linear seperti yang dijelaskan di sini .
sumber
Anda ingin mensimulasikan n-bersarang untuk loop.
Iterasi melalui larik n-dimensi dapat dilihat sebagai peningkatan angka n-digit.
Pada setiap dimensi kita memiliki digit sebanyak panjang dimensi tersebut.
Contoh:
Misalkan kita memiliki array (matriks)
int[][][] T=new int[3][4][5];
dalam "untuk notasi" kita memiliki:
for(int x=0;x<3;x++) for(int y=0;y<4;y++) for(int z=0;z<5;z++) T[x][y][z]=...
untuk mensimulasikan ini, Anda harus menggunakan "notasi angka n-digit"
Kami memiliki 3 digit angka, dengan 3 digit untuk pertama, 4 untuk kedua dan lima untuk digit ketiga
Kita harus menambah angkanya, jadi kita akan mendapatkan urutannya
0 0 0 0 0 1 0 0 2 0 0 3 0 0 4 0 1 0 0 1 1 0 1 2 0 1 3 0 1 4 0 2 0 0 2 1 0 2 2 0 2 3 0 2 4 0 3 0 0 3 1 0 3 2 0 3 3 0 3 4 and so on
Jadi Anda dapat menulis kode untuk meningkatkan angka n-digit tersebut. Anda dapat melakukannya sedemikian rupa sehingga Anda dapat memulai dengan nilai apa pun dari nomor tersebut dan menambah / mengurangi digit dengan angka apa pun. Dengan begitu, Anda dapat mensimulasikan loop bersarang yang dimulai di suatu tempat di tabel dan tidak selesai di akhir.
Ini bukanlah tugas yang mudah. Saya tidak dapat membantu dengan notasi matlab sayangnya.
sumber