亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關于ndarray的形狀不可知切片

關于ndarray的形狀不可知切片

長風秋雁 2019-11-19 10:09:15
在這篇文章中,我使用切片一詞來指代B_i某個維度的n維數組的子數組,A例如size(B_i, d)1 d。 A由此size(A, d)類切片組成,這些切片沿著維度串聯在一起d。例如,如果ndims(A)為6且d為3,則該形式的表達式A(:, :, i, :, :, :)for iin 1:size(A, d)表示組成的所有切片(沿維度d)A。像這樣的表達式存在的問題A(:, :, i, :, :, :)是,它不能被符號化地概括為具有多個不同于6的維數的數組中沿3的維數A的切片。例如,要獲得沿2的維的切片,則需要一個不同的表達式,A(:, i, :, :, :, :)。這意味著這樣的表達式在對要從中提取切片的某些數組的形狀不可知的代碼中毫無用處。下面的功能是我的matlab-noob嘗試實現形狀不可知的切片。(名稱slice已經被使用,因此我將其稱為函數hslice,簡稱hyperslice。)函數的策略是將輸入數組重塑為合適的3-d數組,沿著重塑后的數組的第二維獲取所需的切片,并將結果重塑為具有原始輸入數組的切片形狀。function out = hslice(ndarray, d, i)    sz = size(ndarray);    pfx = sz(1:d-1);    % dimensions before d    sfx = sz(d+1:end);  % dimensions after d    tmp = reshape(ndarray, prod(pfx), sz(d), prod(sfx));    out = reshape(tmp(:, i, :), [pfx 1 sfx]);end是否有內置的或至少更有效的方式來實現相同的結果(與形狀無關的方式)?
查看完整描述

3 回答

?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

是的 您可以使用取消引用的單元格數組和“逗號分隔的列表”之間的等價關系,也可以使用char':'作為索引來動態構造A(:, :, :, i, :, ...)任意維度的調用這一事實。


function out = slice(A, ix, dim)


subses = repmat({':'}, [1 ndims(A)]);

subses{dim} = ix;

out = A(subses{:});

這將完全概括化A(:, :, i, :, ...),除了將這些字符串打亂以進行設置之外,還將執行與原始靜態表達式完全相同的“切片”索引操作。


或者,如果您愿意,可以只將sprintf其構造A(:, :, i, :, ...)為字符串,然后調用eval()它。但我想盡可能避免eval。


請注意,您最初的實現使用的是快速操作,并且應該執行得很好,大約和這個操作一樣快。我之所以發布此內容,是因為我認為它非常易讀,確實可以回答您最初提出的問題,并且可以應用于其他有用的內容。


分配給切片

您還可以使用與單元格相同的下標作為左值將其分配給數組的切片。但是,您不能直接重用slice函數,因為它返回數組的提取子集,而不是左值引用。因此,您可以創建一個非常相似的函數來執行分配。


function A = slice_assign(A, ix, dim, B)

%SLICE_ASSIGN Assign new values to a "slice" of A


subses = repmat({':'}, [1 ndims(A)]);

subses{dim} = ix;

A(subses{:}) = B;

在實踐中,您可能還需要一個僅返回單元格數組中計算出的索引的函數,因此您可以隨身攜帶這些索引,并重復使用它們進行賦值和引用。


function out = slice_subs(A, ix, dim)


subses = repmat({':'}, [1 ndims(A)]);

subses{dim} = ix;

out = subses;


查看完整回答
反對 回復 2019-11-19
?
阿晨1998

TA貢獻2037條經驗 獲得超6個贊

您可以嘗試permute,并setdiff以該維度移動到一貫立場:


function out = hslice(ndarray, d, i)

subdims = setdiff(1:ndims(ndarray),d);

sz = size(ndarray);

outsz = sz(subdims);

order = [d subdims];

ndarray = permute(ndarray,order);

out = reshape(ndarray(i,:),outsz);

end

例如:


d = 3; i = 2;

nd = randi(23,3,3,3,2);

out = hslice(nd,d,i);   % out = squeeze(nd(:,:,i,:)) for d=3

但是,在切片之前,數據將被重寫,而不是與問題中的代碼一起被重寫。因此,我實際上會選擇OP!


查看完整回答
反對 回復 2019-11-19
?
手掌心

TA貢獻1942條經驗 獲得超3個贊

如果您要重寫subsref,則可以為普通類不支持的索引類型定義行為。例如,您可以{}支持任意字符串輸入,而不僅限于':',也可以.采用數字作為參數。我用了一段時間,使它{}成為內存關系類的RESTRICT操作,并.成為支持按名稱或位置索引列的PROJECT。例如selection = r{''WHERE trade_date > today & price < 14''};。

查看完整回答
反對 回復 2019-11-19
  • 3 回答
  • 0 關注
  • 749 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號