In Haskell, there is a structure called 'tuples' which allows two elements to be paired together (Ie: (1,2), ('A', 'B') etc)
I was wondering if there was something similar in Matlab so that I could match elements and then query matlab in a way similar to "If element X is matched to Y then.. else.."
Thanks!
The closet thing I know of in MATLAB is to use a map object. They are pretty easy to use. You can create one as follows
someMap = containers.Map();
Adding a new key is pretty easy as well
someMap('someKey') = 'someValue';
The key needs to be a string by default, but this can be edited. You can also check if the key exists already by calling
someMap.isKey('someKey')
And values are accessed by just calling
someMap('someKey')
This should mimic the behavior that you are looking for. You can always read more by looking at the documentation. containers.Map
A simple cell array may be able to do the trick for you:
C = {1, 2; 'A' 'B'}
You can now easily perform tests on it, for example:
strcmp(C, 'A')
Related
Prologue:
I am in the process of designing/prototyping a piece of code in Matlab.
As at the moment it is not clear to me which matrices should be returned by my functions, I chose, as a general approach, to bind my returned values in containers.Map (as I would do e.g. in python).
Hence, the general setting is
function output = myfoo(args)
output = containers.Map;
...some stuff
output('outname1') = ...
output('outname2') = ...
end
this approach should have the advantage of allowing me to add more returned data without messing up the other code too much or break backwards compatibility.
Issue:
How to deal in a elegant way with matrix slicing?
Say that I need to do something like
output('outname1')(2:end) = ...
(which gives an error as two indexes are not allowed and a boring workaround like
temp = output('outname1')
temp(2:end) = ...
output('outname1') = temp
is required).
Question:
Is there a proficient way to deal with this, avoiding all this referencing/copying job?
No, there is no way to do it without a temporary variable. The only case in which a double index is valid in Matlab is for a cell array. In that case, you can use
output{...}(...)
However, in any other case, a double index results in an error.
Is there an idiomatic way in Matlab to bind the value of an expression to the nth return value of another expression?
For example, say I want an array of indices corresponding to the maximum value of a number of vectors stored in a cell array. I can do that by
function I = max_index(varargin)
[~,I]=max(varargin{:});
cellfun(#max_index, my_data);
But this requires one to define a function (max_index) specific for each case one wants to select a particular return value in an expression. I can of course define a generic function that does what I want:
function y = nth_return(n,fun,varargin)
[vals{1:n}] = fun(varargin{:});
y = vals{n};
And call it like:
cellfun(#(x) nth_return(2,#max,x), my_data)
Adding such functions, however, makes code snippets less portable and harder to understand. Is there an idiomatic to achieve the same result without having to rely on the custom nth_return function?
This is as far as I know not possible in another way as with the solutions you mention. So just use the syntax:
[~,I]=max(var);
Or indeed create an extra function. But I would also suggest against this. Just write the extra line of code, in case you want to use the output in another function. I found two earlier questions on stackoverflow, which adress the same topic, and seem to confirm that this is not possible.
Skipping outputs with anonymous function in MATLAB
How to elegantly ignore some return values of a MATLAB function?
The reason why the ~ operator was added to MATLAB some versions ago was to prevent you from saving variables you do not need. If there would be a syntax like the one you are searching for, this would not have been necessary.
I came across some matlab code that did the following:
thing.x=linspace(...
I know that usually the . operator makes the next operation elementwise, but what does it do by itself? Is this just a sub-object operator, like in C++?
Yes its subobject.
You can have things like
Roger.lastname = "Poodle";
Roger.SSID = 111234997;
Roger.children.boys = {"Jim", "John"};
Roger.children.girls = {"Lucy"};
And the things to the right of the dots are called fields.
You can also define classes in Matlab, instatiate objects of those classes, and then if thing was one of those objects, thing.x would be an instance variable in that object.
The matlab documentation is excellent, look up "fields" and "classes" in it.
There are other uses for ., M*N means multiploy two things, if M, N are both matrices, this implements the rules for matrix multiplication to get a new matrix as its result. But M.*N means, if M, N are same shape, multiply each element. And so no like that with more subtleties, but out of scope of what you asked here.
As #marc points out, dot is also used to reference fields and subfields of something matlab calls a struct or structure. These are a lot like classes, subclasses and enums, seems to me. The idea is you can have a struct data say, and store all the info that goes with data like this:
olddata = data; % we assume we have an old struct like the one we are creating, we keep a reference to it
data.date_created=date();
data.x_axis = [1 5 2 9];
data.notes = "This is just a trivial example for stackoverflow. I didn't check to see if it runs in matlab or not, my bad."
data.versions.current = "this one";
data.versions.previous = olddata;
The point is ANY matlab object/datatype/whatever you want to call it, can be referenced by a field in the struct. The last entry shows that we can even reference another struct in the field of a struct. The implication of this last bit is we could look at the date of creation of the previous verions:
data.versions.previous.date_created
To me this looks just like objects in java EXCEPT I haven't put any methods in there. Matlab does support java objects which to me look a lot like these structs, except some of the fields can reference functions.
Technically, it's a form of indexing, as per mwengler's answer. However, it can also be used for method invocation on objects in recent versions of MATLAB, i.e.
obj.methodCall;
However note that there is some inefficiency in that style - basically, the system has to first work out if you meant indexing into a field, and if not, then call the method. It's more efficient to do
methodCall(obj);
I have a struct array called AnalysisResults, that may contain any MATLAB datatypes, including other struct arrays and cell arrays.
Then I have a string called IndexString, which is the index to a specific subfield of StructArray, and it may contain several indices to different struct arrays and cell arrays, for example:
'SubjectData(5).fmriSessions{2}.Stats' or 'SubjectData(14).TestResults.Test1.Factor{4}.Subfactor{3}'.
And then I have a variable called DataToBeEntered, which can be of any MATLAB datatype, usually some kind of struct array, cell array or matrix.
Using eval, it is easy to enter the data to the field or cell indexed by IndexString:
eval([ 'AnalysisResults.', IndexString, ' = DataToBeEntered;' ])
But is it possible to avoid using eval in this? setfield doesn't work for this.
Thank you :)
Well, eval surely is the easiest way, but also the dirtiest.
The "right" way to do so, I guess, would be to use subsasgn. You will have to parse the partial MATLAB command (e.g. SubjectData(5).fmriSessions{2}.Stats) into the proper representation for those functions. Part of the work can be done by substruct, but that is the lightest part.
So for example, SubjectData(5).fmriSessions{2}.Stats would need to be translated into
indexes = {'.' , 'SubjectData',
'()', {5},
'.' , 'fmriSessions',
'{}', {2},
'.' , 'Stats'};
indexStruct = substruct(indexes{:});
AnalysisResult = subsasgn(AnalysisResult, indexStruct, DataToBeEntered);
Where you have to develop the code such that the cell array indexes is made as above. It shouldn't be that hard, but it isn't trivial either. Last year I ported some eval-heavy code with similar purpose and it seemed easy, but it is quite hard to get everything exactly right.
You can use dynamic field names:
someStruct.(someField) = DataToBeEntered;
where someField is a variable holding the field name, but you will have to parse your IndexString to single field name and indices.
If I have an ArrayList<Double> dblList and a Predicate<Double> IS_EVEN I am able to remove all even elements from dblList using:
Collections2.filter(dblList, IS_EVEN).clear()
if dblList however is a result of a transformation like
dblList = Lists.transform(intList, TO_DOUBLE)
this does not work any more as the transformed list is immutable :-)
Any solution?
Lists.transform() accepts a List and helpfully returns a result that is RandomAccess list. Iterables.transform() only accepts an Iterable, and the result is not RandomAccess. Finally, Iterables.removeIf (and as far as I see, this is the only one in Iterables) has an optimization in case that the given argument is RandomAccess, the point of which is to make the algorithm linear instead of quadratic, e.g. think what would happen if you had a big ArrayList (and not an ArrayDeque - that should be more popular) and kept removing elements from its start till its empty.
But the optimization depends not on iterator remove(), but on List.set(), which is cannot be possibly supported in a transformed list. If this were to be fixed, we would need another marker interface, to denote that "the optional set() actually works".
So the options you have are:
Call Iterables.removeIf() version, and run a quadratic algorithm (it won't matter if your list is small or you remove few elements)
Copy the List into another List that supports all optional operations, then call Iterables.removeIf().
The following approach should work, though I haven't tried it yet.
Collection<Double> dblCollection =
Collections.checkedCollection(dblList, Double.class);
Collections2.filter(dblCollection, IS_EVEN).clear();
The checkCollection() method generates a view of the list that doesn't implement List. [It would be cleaner, but more verbose, to create a ForwardingCollection instead.] Then Collections2.filter() won't call the unsupported set() method.
The library code could be made more robust. Iterables.removeIf() could generate a composed Predicate, as Michael D suggested, when passed a transformed list. However, we previously decided not to complicate the code by adding special-case logic of that sort.
Maybe:
Collection<Double> odds = Collections2.filter(dblList, Predicates.not(IS_EVEN));
or
dblList = Lists.newArrayList(Lists.transform(intList, TO_DOUBLE));
Collections2.filter(dblList, IS_EVEN).clear();
As long as you have no need for the intermediate collection, then you can just use Predicates.compose() to create a predicate that first transforms the item, then evaluates a predicate on the transformed item.
For example, suppose I have a List<Double> from which I want to remove all items where the Integer part is even. I already have a Function<Double,Integer> that gives me the Integer part, and a Predicate<Integer> that tells me if it is even.
I can use these to get a new predicate, INTEGER_PART_IS_EVEN
Predicate<Double> INTEGER_PART_IS_EVEN = Predicates.compose(IS_EVEN, DOUBLE_TO_INTEGER);
Collections2.filter(dblList, INTEGER_PART_IS_EVEN).clear();
After some tries, I think I've found it :)
final ArrayList<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5);
Iterables.removeIf(Iterables.transform(ints, intoDouble()), even());
System.out.println(ints);
[1,3,5]
I don't have a solution, instead I found some kind of a problem with Iterables.removeIf() in combination with Lists.TransformingRandomAccessList.
The transformed list implements RandomAccess, thus Iterables.removeIf() delegates to Iterables.removeIfFromRandomAccessList() which depends on an unsupported List.set() operation.
Calling Iterators.removeIf() however would be successful, as the remove() operation IS supported by Lists.TransformingRandomAccessList.
see: Iterables: 147
Conclusion: instanceof RandomAccess does not guarantee List.set().
Addition:
In special situations calling removeIfFromRandomAccessList() even works:
if and only if the elements to erase form a compact group at the tail of the List or all elements are covered by the Predicate.