I am trying to fill an empty cell array with mixed numeric and string data to subsequently write to Excel and have come up with a problem. The following MCVE should reproduce the issue:
First, I create the cell array and set the top left element to an empty string. So far so good:
xls_array = cell(7,6);
xls_array{1,1} = '';
Then I need to populate the first line and the first column of the array with their respective headers. These are variables (cell arrays) created elsewhere in the code, but for the purpose of the MCVE, I have created some artificial ones:
col_headers = {'Channel 1';'Channel 2';'Channel 3';'Channel 4';'Channel 5'};
xls_array(1,2:end) = col_headers';
row_headers = {'Var A';'Var B';'Var C';'Var D';'Var E';'Var F'};
xls_array(2:end,1) = row_headers;
So far, so good. Now I need to add the actual data to the cell array and that's where the problem arises. Again, for the purpose of the MCVE, I have generated some random data:
data = rand(6,5);
xls_array{2:end,2:end} = data;
This gives me the following error message:
>> xls_array{2:end,2:end} = data;
error: invalid dot name structure assignment because the structure array is empty. Specify a subscript on the structure array to resolve.
If I try normal brackets instead of curly brackets, it doesn't error out but doesn't give me the expected result either:
xls_array(2:end,2:end) = data;
>> xls_array{2,2}
ans =
0.326180 0.169640 0.381373 0.416490 0.283456
0.350000 0.366084 0.409047 0.619715 0.962095
0.526219 0.466591 0.553932 0.930187 0.460585
0.983679 0.324129 0.964619 0.080852 0.786360
0.069995 0.835966 0.266789 0.673177 0.796602
0.741368 0.233794 0.022568 0.012975 0.248514
i.e. it has copied the entire numeric array data in each element of the cell array xls_array(2:end,2:end).
What I want instead is to copy data into the remaining blank cells of the cell array, i.e. data(1,1) should be in xls_array{2,2}, data(1,2) in xls_array{2,3}, etc...
I have also tried the following, to no avail:
>> xls_array{2:end,2:end}(:) = data;
error: a cs-list cannot be further indexed
Can anybody help?
You need to convert the numeric array to a cell array and use parentheses for indexing:
xls_array(2:end,2:end) = num2cell(data);
Curly brackets can be used this way:
[xls_array{2:end,2:end}] = num2cell(data){:};
Alternatively you can use the concatenation operator to create the result:
xls_array = [{''}, col_headers.'; row_headers, num2cell(data)];
Why other methods don't work?
Curly brackets are used for a special type of indexing which returns the contents of a cell array as a comma separated list . If the LHS is a comma separated list the RHS should be also be a comma separated list that the number of its elements isn't less than the that of LHS and square brackets should be used around the LHS. More about comma separated lists can be found in the documentation. So xls_array{2:end,2:end} = data; is wrong because data can be interpreted as a comma separates list containing only one element but the LHS requires more elements and also the square brackets are missing.
The example xls_array(2:end,2:end) = data; I think is a bug in Octave because a cell array is an array that the type of its elements is cell. When parentheses are used for normal cell indexed assignment, the right hand side of the assignment should be of type cell and there is no implicit conversion form other types to cell type. So xls_array(2:end,2:end) = data; should be wrong because data is of double type. However we can see that the behavior of Octave is that data is implicitly converted to a cell {data} and then assigned to elements of LHS.
Related
I've tried creating a 'real' type value array in the following way in Icarus Verilog:
parameter width = 10;
shortreal b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181};
Gives the following error:
error: Cannot assign to array b. Did you forget a word index?
I went through the icarus verilog src code error messages and the explanation to this one is "Special case: The l-value is an entire memory, or array
slice". This is, in fact, an error in l-values. Detect the
situation by noting if the index count is less than the
array dimensions (unpacked)", which I assume means that the array index size differs from the declared one [width-1:0], which isn't true if I understand.
I've also tried:
parameter width = 10;
parameter [32:0] b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181};
but without any success.
Using Icarus Verilog with -g2012 flag (for SV support)
It is only legal to use so-called array concatenation if you fill the entire array. You array have 10 elements, but there are only 9 on the right hand side:
parameter width = 10;
shortreal b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181,0.0181};
Suppose I have non-scalar structure
res = struct(); res(1).name = 'hello'; res(2).name = 'world';
Now I want to copy entire content of name field to another field, say tag.
Neither of the following worked:
>> res.tag = res.name;
Scalar structure required for this assignment.
>> [res.tag] = [res.name];
Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
>> {res.tag} = {res.name};
{res.tag} = {res.name};
↑
Error: The expression to the left of the equals sign is not a valid target for an assignment.
Any other ideas?
Use
[res(:).tag] = res(:).name;
or more simply, as you have discovered yourself:
[res.tag] = res.name;
The syntax with square brackets on the left-hand side is similar to that used for capturing several outputs returned by a function: [out1, out2] = fun(...); see MATLAB special characters.
Actually, the syntax res.tag produces a comma-separated list; and [...] is standard for assigning values to each element in one such list; see Assigning output from a comma-separated list.
The right-hand side of the assignment should be another comma-separated list. If it is a single element, or you want to specify a list manually, you need deal:
values = {10, 20};
[res.test] = values{:}; % works. {:} produces a comma-separated list
[res.test] = 10,20; % doesn't work. Use `deal`
[res.test] = deal(10,20); % works
[res.test] = 10; % doesn't work, unless `res` is scalar. Use `deal`
[res.test] = deal(10); % also works. 10 is repeated as needed
The reason why your attempt [res.tag] = [res.name]; doesn't work is that [res.name] on the right-hand side concatenates the results of the comma-separated list res.name into one array, and so it's the same case as [res.test] = 10; above.
I am writing a method which accepts a two dimensional array of doubles and an int row number as parameters and returns the highest value of the elements in the given row.
it looks like this:
function getHighestInRow(A, i)
return(maximum(A[:i,:]))
end
the issue i am having is when i slice the array with
A[:i,:]
I get an argument error because the :i makes i get treated differently.
the code works in the other direction with
A[:,i,:]
Is there a way to escape the colon? so that i gets treated as a variable after a colon?
You're doing something strange with the colon. In this case you're using the symbol :i not the value of i. Just getHighestInRow(A,i) = maximum(A[i,:]) should work.
Edit: As Dan Getz said in the comment on the question, getHighestInRow(A,i) = maximum(#view A[i,:]) is more efficient, though, as the slicing will allocate a temporary unnecessary array.
The point of indexing is mainly to get the value. In MATLAB,
for a cell array, there is content indexing ({}), and thus cell indexing (()) is only for selecting a subset from the cell array, right?
Is there anything other advanced usage for it? Like using it as
a pointer and pass it to a function?
There is a heavily simplified answer. {}-indexing returns you the content, ()-indexing creates a subcell with the indexed elements. Let's take a simple example:
>> a=x(2)
a =
[2]
>> class(a)
ans =
cell
>> b=x{2}
b =
2
>> class(b)
ans =
double
Now continue with non-scalar elements. For the ()-indexing everything behaves as expected, you receive a subcell with the elements:
>> a=x(2:3)
a =
[2] [3]
The thing really special to Matlab is using {}-indexing with non-scalar indices. It returns a Comma-Separated List with all the contents. Now what is happening here:
>> b=x{2:3}
b =
2
The Comma-Separated List behaves similar to a function with two return arguments. You want only one value, only one value is assigned. The second value is lost. You can also use this to assign multiple elements to individual lists at once:
>> [a,b]=x{2:3} %old MATLAB versions require deal here
a =
2
b =
3
Now finally to a very powerful use case of comma separated lists. Assume you have some stupid function foo which requires many input arguments. In your code you could write something like:
foo(a,b,c,d,e,f)
Or, assuming you have all parameters stored in a cell:
foo(a{1},a{2},a{3},a{4},a{5},a{6})
Alternatively you can call the function using a comma separated list. Assuming a has 6 elements, this line is fully equivalent to the previous:
foo(a{:}) %The : is a short cut for 1:end, index the first to the last element
The same technique demonstrated here for input arguments can also be used for output arguments.
Regarding your final question about pointers. Matlab does not use pointers and it has no supplement for it (except handle in oop Matlab), but Matlab is very strong in optimizing the memory usage. Especially using Copy-on-write makes it unnecessary to have pointers in most cases. You typically end up with functions like
M=myMatrixOperation(M,parameter,parameter2)
Where you input your data and return it.
I have this bit of code:
var arrayIntegers : [Int] = []
arrayIntegers += 0...33
var arrayDecimal : [Int] = []
arrayDecimal += 0...999
The problem is I can´t convert the values of both arrays to Double. What I want to do is to get a new array (called arrayDoubleComposed) with composite values, taking a value of arrayIntegers as the integer part and then taking another value of arrayDecimal as the floating part.
When I try to typecast this:
var arrayDoubleComposed : [Double] = []
arrayDoubleComposed = Double (arrayIntegers[] + (arrayDecimal[])/1000)
I´ve got an error. The same if I suppress the [].
I´m a little bit newcomer, I know...
Converting one kind of array into another is a job for map, which applies a function to each element of an array, returning the results as a new array of the type that function returns. In this case, you want a function that converts the Ints to a Double.
Try something like this:
let integers = Array(0...33)
let fractions = Array(0...999)
let arrayDoubleComposed = map(Zip2(integers, fractions)) {
(i, f) in
Double(i) + Double(f)/1_000
}
Zip2 takes two sequences and pairs them up – first elements together, second elements together etc. Then this passes that into map which combines the two elements.
(note also you can just initialize the arrays from the ranges rather than declaring them then adding the values)
It’s not clear what you mean to do, as the integer and fractional arrays are going to be different length. The way Zip2 handles this is to stop when the first sequence runs out, but this may not be what you want.
P.S. casts like the one you tried, which convert the contents of an array en-mass, only work in special cases when converting from Objective-C types to native Swift types, when the Swift compiler sprinkles some magic.