Creating a Cell Array but I've Got The Size Wrong and Its Missing Certain Elements
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
This section of code is meant to take an even number of input arguments and return them as a cell array with two columns, one for the name and one for the value. With the test input I've been given it is only returning the the third and forth input arguments as a 1x1 cell array where as I'm looking for a 2x2 cell array. Is the issue with the ii indexing? Can I not do it like I've written here?
db = name_value_pairs('name','John Smith','age',32)
function [db]=name_value_pairs(varargin)
for ii = 1:2:(length(varargin)-1)
for i = 1:(length(varargin)/2)
x(i,1) = varargin(ii);
end
end
for ii = 2:2:length(varargin)
for i = 1:(length(varargin)/2)
x(i,2) = varargin(ii);
end
end
db = {x};
end
db =
1×1 cell array
{2×2 cell}
Thank you for any help or advice!
채택된 답변
The logic in your code seems to over-kill for this task. db = {x} statement make the return value a 1x1 array. If you change it to db = x you will get a 2x2 array.
You can use reshape() to write a one-liner
function [db]=name_value_pairs(varargin)
db = reshape(varargin, 2, []).';
end
댓글 수: 10
Thank you Ameer! So I tried both suggestions and each one improved the output a little but I'm still not there. Changing db ={x} to db = x returend the right sized array but I'm still overwriting data:
db = % using db = x
2×2 cell array
{'age'} {[32]}
{'age'} {[32]}
The reshape function is great however it returns 'name' and 'age' in the first row where as I need tham in the first column. I checked the help documentation for reshape() but I didn't see a method to switch those. Is it possible to transpose a cell array like you can with a matrix?
db = % using reshape()
2×2 cell array
{'name' } {'age'}
{'John Smith'} {[ 32]}
EDIT: So you I've determined you can transpose a cell array, so thanks to you I've solved the main issue! Tangentially related to this, can I use ischar() to verify whether the name column, the first column, contains only character arrays?
I am glad to be of help!
Yes, The logic of for-loop is not correct, and it just makes the code complex. reshape() is a cleaner option.
You can use ischar() like this to see which of the values in first columns are character arrays.
cellfun(@ischar, db(:,1))
Again thank you so much. My only remaining issue is the failure of my if-else statements:
function [db]=name_value_pairs(varargin)
if nargin < 2
db ={};
elseif rem(nargin, 2) ~= 0 % I thought this would check for even # of inputs
db ={};
else
x = reshape(varargin, 2, []);
db = x';
end
if cellfun(@ischar, db(:,1)) ~= 1
db = {};
else
db = db;
end
end
If there are not an even number of inputs then db should be an empty cell array but when I try using:
db = name_value_pairs('name','John Smith','age')
I get an error that the index in position 2 exceeds the array bounds. But when that condition is encountered I was expecting the code to return an empty cell array. I'm a bit miffed at this error since if-else statements are pretty basic and I thought I had a good grasp on them.
The error happens because if you have an odd number of inputs, the first if-block return db={}, but then in the second if-block you are trying to access db(:,1) [first column of db]. Therefore, MATLAB throws an error since there is no first column.
Check the following code
function [db]=name_value_pairs(varargin)
if rem(nargin, 2) ~= 0 % I thought this would check for even # of inputs
db ={};
else
x = reshape(varargin, 2, []);
db = x';
if cellfun(@ischar, db(:,1)) ~= 1
db = {};
end
end
end
if cellfun(@ischar, db(:,1))
ischar returns 1 if true and 0 if false correct? That check isn't working with the input
db = name_value_pairs(13,'John Smith','age', 32)
as it returns a 2x2 cell array with 13 in place of name. In the line above I set db = x' but the nested if statement should return an empty array if ischar is false right?
I finally got the char test condition to work. I thought that cellfun(@ischar, db(:,1)) ~= 1 would check that ALL cell values in the first column are character arrays. It does not and still passes as long as one of them is a char. So my current version of the function is this:
function [db]=name_value_pairs(varargin)
myCell = varargin;
if nargin < 2
db ={};
elseif rem(nargin, 2) ~= 0
db ={};
elseif sum(cellfun(@ischar, myCell(1:3))) ~= 3
db = {};
else
x = reshape(varargin, 2, []);
db= x';
end
end
I've almost passed the assignment but I'm still failing the Random Inputs test. Unfortunately the automatic grader isn't displaying what those inputs are so I can't really work on a solution. I made a post in the class forum so hopefully one of the instructors responds. I suspect that the random inputs are just random strings. The ischar test condition should check for those right?
"The ischar test condition should check for those right?"
Sort of... note that character arrays can have any size, including any number of rows or pages, etc. So ischar returns true for a 2x3 character matrix and for a 5x3x2 character array and even for a 0x0x1 character array. It is possible that the automatically generated tests include such cases, but that they expect the test to only pass for row vectors, i.e. character arrays where ndims==2 and the number of rows==1.
Another problem is that cellfun() will return an array, which can create unexpected results when directly used with if-statement. Using sum(cellfun(@ischar, myCell(1:3))) ~= 3. Which only works when if there are three rows, and myCell(1:3) is also not correct to use here.
Try this code
function [db]=name_value_pairs(varargin)
if rem(nargin, 2) ~= 0 % I thought this would check for even # of inputs
db ={};
else
x = reshape(varargin, 2, []);
db = x';
if all(cellfun(@ischar, db(:,1)))
db = {};
end
end
end
Thank you Stephen and Ameer. Ameer, shouldn't it be:
if all(cellfun(@ischar, db(:,1)))
db = db;
else
db = {};
end
Or something similar? The way you have it written if @ischar is true then db is set as an empty array, right?
EDIT: Ok, finally got it!
function [db]=name_value_pairs(varargin)
if nargin < 2
db ={};
elseif rem(nargin, 2) ~= 0
db ={};
else
x = reshape(varargin, 2, []);
z = x';
if all(cellfun(@ischar, z(:,1)))
db = z;
else
db = {};
end
end
end
Thank you both so much, especially you Ameer. I appreciate the help and your endless patience.
Yes, you are correct. The condition should be reversed. The following is also equivalent.
function [db]=name_value_pairs(varargin)
if rem(nargin, 2) ~= 0 % I thought this would check for even # of inputs
db ={};
else
db = reshape(varargin, 2, []);
if ~all(cellfun(@ischar, db(:,1)))
db = {};
end
end
end
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Matrix Indexing에 대해 자세히 알아보기
제품
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
