I've just started with MATLAB, having mainly played around with Python previously. I've just made my first associative array, and am a little confused with how it's dealing with commas and spaces. My array is:
co_comma=containers.Map({'Open University','UCL',' University of Edinburgh','Birkbeck'},{193835,21210,24525,17822})
I also made a second associative array, splitting using spaces:
co_space=containers.Map({'Open University' 'UCL' ' University of Edinburgh' 'Birkbeck'},{193835 21210 24525 17822})
They both give the following:
Map with properties:
Count: 4
KeyType: char
ValueType: double
But co_comma==co_space gives False:
ans =
logical
0
Questions:
how are these associative arrays different
what actually is a container? Although I've never thought of lists etc in this way, Python seems to have containers in the form of lists/tuples/general iterables - https://stackoverflow.com/a/11576019/11357695. So is a matlab string container vs a matlab char array different in the same way as (for example) python lists and python tuples are different?
Thanks :D
Many things mixed in here!
Clarifications:
A matlab container is only equivalent to a python dictionary, not a list/tuple/general iterable.
Both of your containers are created the same. You seem to be naming them comma and space, but this distinction does not even reach the definition of the container.
Both {'Open University','UCL',' University of Edinburgh','Birkbeck'} and {'Open University' 'UCL' ' University of Edinburgh' 'Birkbeck'} create the exact same cell array, so the input to container.map is the same. you are comparing a=[5]; and b=5, as a MATLAB-valid analogy. They are the same.
For objects, most programing languages (including python!) will give you false when you compare two objects that contain the same values, yet are different objects. Only basic variables tend to compare by value, and not by some sort of objecID. In your case, simply doing isequal(co_comma,co_space) will return true, so their values are the same (as we already know, from the previous point)
Containers are not generally used in MATLAB, unless you specifically want a dictionary.
So here's the deal with Matlab: Matlab is an oddball. In Matlab, everything is an array, and there is no real distinction between regular "values" and "containers" or "collections" like there is in many programming languages. In Matlab, any numeric value is a numeric array. Any string value is actually an array of strings. Every value is iterable and can be used in a for loop or other "list"-like context. And every type or class in Matlab must implement collection/container behaviors as well as its "plain" value semantics.
Scalar values in Matlab are actually degenerate cases of two-dimensional arrays that are 1-by-1 in size. The number 42? Actually a 1-long array of doubles. The string "foo"? Actually a 1-long array of strings. Everything in Matlab is actually like a list in Python (or, more accurately, a NumPy series or array).
A cell array is an array of things, which can contain any other type of array in each of its elements. This is used for heterogeneous collections.
A char array is a bit weird, because it is used to represent strings, but its elements are not themselves strings, but rather characters. Plain char arrays are used in a weird way to represent lists of strings: you make a 2-D char array, and read each row as a string that is padded with spaces on the right. Lists of strings that are different lengths used to be represented as "cellstrs", which are cell arrays that contain char row vectors in each element. It's weird; see my blog post about it. The new string array makes most uses of other string types obsolete. You might want to use strings here. In Matlab, string literals are double-quoted, and char literals are single-quoted.
The word "container" doesn't have a specific technical meaning in Matlab, and is not really a thing. There's the containers package, but the only thing in it is containers.Map; there are no other types of containers and no generalization of what it means to be a container. One of the Matlab developers had an idea for making containers like this, but it never really went anywhere. And as far as I can tell, containers.Map hardly gets used at all: containers.Map is a pass-by-reference "handle" object, whereas most Matlab types are pass-by-value, so Map can't be used easily with most Matlab code.
So, putting aside the weirdness of chars, everything in Matlab has array semantics, and is effectively an iterable container like Python lists or tuples. And in Matlab, most values and objects are immutable and pass-by-value, so they are more like Python tuples than Python lists.
Related
Now that string array is a thing since R2016b, is there a native function that export a string array to csv file and vice versa?
A function that fills the same role of csvread and csvwrite for numeric arrays in the old days but for string arrays. And to relax the requirement, say the string array contains columns of pure strings and columns of pure doubles. Stock prices with time stamp strings would be an example.
Native = not looping with fprintf. But if you are certain Matlab hasn't included any such functions yet, feel free to answer with the best approach thusfar without any restrictions.
Without any native function, pre-R2013a, looping with fprintf is the only way I can think of. And it was awful. Given past reputation of inefficiency, I still don't trust looping in Matlab.
Post-R2016b, one can convert a string array to cell array with num2cell and then to table with cell2table. Table can be written to csv file with writetable. This is actually fast, as writetable is fast. Only num2cell slows down the whole process a little. However, formatting is impossible along the way.
Post-R2019a, cell2table can be skipped with writecell, which is nice but the time consuming (slightly) step is num2cell and formatting should still be impossible. (I don't have R2019a to test it.)
Is there a better way or is it another one of those basic things left to be desired about Matlab?
writematix and readmatrix are the functions to do that since R2019a.
%If S1 is a string array that you want to `foobar.csv` then:
writematrix(S1,'foobar.csv');
%To read this csv file back into MATLAB as the same string array, use:
S2 = readmatrix('foobar.csv','OutputType','string');
%Verifying the result:
isequal(S1,S2)
ans =
logical
1
Loops have been significantly improved since R2015b. Not all loops are slow and not all vectorised versions are faster. The correct approach is to timeit when in doubt.
In MATLAB, the i-th element of an array is accessed by a(i), while the i-th element of a cell is accessed by a{i}. So my code has to do different things in terms of whether a is a cell or not.
Is there a better way to do it? so we can access the i-th element in a 'same'? way.
You can access the ith element of any array in the same way, a(i), and the behaviour is completely uniform: you get back an object of the same class as a. So if a is a 5x5 double array, a(i) is a 1x1 double. Similarly, if a is a cell array, then a(i) is a 1x1 cell. So far, so logical and consistent.
Now, if you want to look inside a cell, you use a{i} but that is a fundamentally different operation. Your question seems to imply that it would be "better" if these two fundamentally different operations had the same syntax. It wouldn't: if this were the case, then the ability to slice a cell array into arbitrary shapes (including 1x1) would be overshadowed.
But you can always write a custom function. Among the many Matlab workarounds I carry with me everywhere, I have the following pair of functions:
function a = ascell(a)
if ~iscell(a), a = {a}; end
and
function a = uncell(a)
if iscell(a) & numel(a) == 1, a = a{1}; end
With uncell.m on your path, b = uncell(a(i)); would give you the ith element of a with the cell wrapping, if any, stripped off.
It is good to have the call to uncell visible in the code because it alerts you (or another maintainer) to the possibility that a might legally be a cell or a non-cell—this is by no means necessarily true in everybody's coding strategy. Nor will my code necessarily follow the same convention as yours when it comes to interpreting the meaning and correct treatment of a cell array where a non-cell was expected, or a non-cell where a cell was expected (and this is another way of explaining why there's no common syntax). This leads me to the question: if the design of your application is such that a can by its nature contain elements with mismatched shapes or types, then why not simply decree that it is always a cell, never a non-cell, and always access the ith element as a{i}?
I have an array of "object" structures, OBJECT_ARRAY, that I must often transform into individual arrays for each element of the object structures. This can be done using arrayfun. It's more tedious than simply refereeing to OBJECT_ARRAY(k).item1, but that's how The Mathworks chose to do it.
In this case today, I have used those individual arrays and calculated a corresponding derived value, newItem, for each element and I need to add this to the original array of structures. So I have an array of newItems.
Is there a straightforward way to do an assignment for each object in OBJECT_ARRAY so that (effectively) OBJECT_ARRAY(k).newItem = newItems(k) for every index k?
I am using version 2015a.
You shouldn't need arrayfun for any of this.
To get values out, you can simply rely on the fact that the dot indexing of a non-scalar struct or object yields a comma-separated list. If we surround it with [] it will horizontally concatenate all of the values into an array.
array_of_values = [OBJECT_ARRAY.item1];
Or if they are all different sizes that can't be concatenated, use a cell array
array_of_values = {OBJECT_ARRAY.item1};
To do assignment, you can again use the comma separated list on the left and right side of the assignment. We first stick the new values in a cell array so that we can automatically convert them to a comma-separated list using {:}.
items = num2cell(newitems);
[OBJECT_ARRAY.item1] = items{:};
If a Julia function returns an array, is the reference returned or a copy?
function pass(A::Matrix)
return A
end
A real example is reshape:
reshape(A, dims)
Create an array with the same data as the given array, but with different dimensions. An implementation for a particular type of array may choose whether the data is copied or shared.
How does the implementation determine whether data is copied or shared?
The pass function above returns by reference, http://julia.readthedocs.org/en/latest/manual/arrays/ .
There is a bit more to the reshape example.
For full arrays the reshaped array is a new array object that shares the same data. But keep in mind that there are plenty of specialized array types. The docs warn you not to rely on that because for example for a future implementation of immutable fixed sized arrays a different reshape mechanism could be used.
for i=1:30
Name(i,1)=sprintf('String_%i',i);
end
I'm just confused what is not working here, this script seems very straightforward, wnat to build a list of strings with numbering from 1 to 30. getting error
Subscripted assignment dimension mismatch.
Matlab do not really have strings, they have char arrays. As in almost any programming language Matlab cannot define a variable without knowing how much memory to allocate. The java solution would look like this:
String str[] = {"I","am","a","string"};
Similar to the c++ solution:
std::string str[] = {"I","am","another","string"};
The c solution looks different, but is generally the same solution as in c++:
const char* str[] = {"I","am","a","c-type","string"};
However, despite the appearances these are all fundamentally the same in the sense to that they all knows how much data to allocate even though they would not be initiated. In particular you can for example write:
String str[3];
// Initialize element with an any length string.
The reason is that the memory stored in each element is stored by its reference in java and by a pointer in c and c++. So depending on operating system, each element is either 4 (32-bit) or 8 (64-bit) bytes.
However, in Matlab matrices data is stored by value. This makes it impossible to store a N char arrays in a 1xN or Nx1 matrix. Each element in the matrix is only allowed to be of the same size as a char and be of type char. This means that if you work with strings you need to use the data structure cell (as also suggested by Benoit_11) which stores a reference to any Matlab object in each element.
k = 1:30;
Name = cell(length(k),1);
for i=k
Name{i,1}=sprintf('String_%i',i);
end
Hope that the explanation makes sense to you. I assumed that according to your attempt you have at least some programming experience from at least one other language than matlab.