Creating a Cell Array but I've Got The Size Wrong and Its Missing Certain Elements
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
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!
Accepted Answer
Ameer Hamza
on 3 Sep 2020
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 Comments
Marcin Laszkiewicz
on 3 Sep 2020
Edited: Marcin Laszkiewicz
on 3 Sep 2020
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))
Marcin Laszkiewicz
on 3 Sep 2020
Edited: Marcin Laszkiewicz
on 3 Sep 2020
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?
Marcin Laszkiewicz
on 4 Sep 2020
Edited: Marcin Laszkiewicz
on 4 Sep 2020
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.
Ameer Hamza
on 4 Sep 2020
Edited: Ameer Hamza
on 4 Sep 2020
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
Marcin Laszkiewicz
on 4 Sep 2020
Edited: Marcin Laszkiewicz
on 4 Sep 2020
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
More Answers (0)
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Products
Tags
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- 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)