I have variables with incremented numbers within, such as row0text, row1text, row2text, etc.
I've figured out how to dynamically create string versions of those variable names, but once I have those strings, how can I use them as actual variable names rather than strings in my code?
Example:
var row3text = "This is the value I need!"
var firstPart = "row"
var rowNumber = 3
var secondPart = "text"
var together = (firstPart+String(rowNumber)+secondPart)
// the below gives me the concatenated string of the three variables, but I'm looking for a way to have it return the value set at the top.
println (together)
Once I know how to do this, I'll be able to iterate through those variables using a for loop; it's just that at the moment I'm unsure of how to use that string as a variable name in my code.
Thanks!
Short Answer: There is no way to do this for good reason. Use arrays instead.
Long Answer:
Essentially you are looking for a way to define an unknown number of variables that are all linked together by their common format. You are looking to define an ordered set of elements of variable length. Why not just use an array?
Arrays are containers that allow you to store an ordered set or list of elements and access them by their ordered location, which is exactly what you're trying to do. See Apple's Swift Array Tutorial for further reading.
The advantage of arrays is that they are faster, far more convenient for larger sets of elements (and probably the same for smaller sets as well), and they come packaged with a ton of useful functionality. If you haven't worked with arrays before it is a bit of a learning curve but absolutely worth it.
Related
Is there any difference between the following?
var array1_OfStrings = [String]()
var array2_OfStrings: [String] = []
var array3_OfStrings: [String]
Testing in Playground shows that 1 and 2 are the same but 3 behaves differently.
Can someone explain me the difference please? And also what will be the preferred way to declare an empty array of String?
First two have the same effect.
declare a variable array1_OfStrings, let it choose the type itself. When it sees [String](), it smartly knows that's type array of string.
You set the variable array2_OfStrings as type array of string, then you say it's empty by []
This is different because you just tell you want array3_OfStrings to be type array of string, but not given it an initial value.
I think the first one is recommended as The Swift Programming Language uses it more often.
While I might be late to the party, there is one thing that needs to be said.
First option set array1_OfStrings to array of Strings
The other option tells that array1_OfStrings is array of Strings and then set it empty.
While this might be a really small difference, you will notice it while compiling. For the first option compiler will automatically try to find out what is the type of array1_OfStrings. Second option won't do that, you will let compiler know that this actually is array of Strings and done deal.
Why is this important? Take a look at the following link:
https://thatthinginswift.com/debug-long-compile-times-swift/
As you can see, if you don't declare type of your variable that might impact build performance A LOT.
I'm having a problem with non-latin character sets, and I need to check that a Range is in bounds before performing .substringWithRange. This seems really easy, but I can't find the way to do this.
Given a range:
let lastCharRange = currentString.endIndex.predecessor() ..< currentString.endIndex
How can I check:
let lastExpected = expectedString.substringWithRange(lastCharRange)
is in bounds?
Indexes are tied closely to the String that generated them -- actually to the String's CharacterView, which is a CollectionType. This holds true generally for collections.
So, you simply can't use the Index you got from one String on another String.
Depending on what you are doing, you might have to get a substring from the first and then search the second. You can also get the two Strings' CharacterViews and work with them via their collection-based interface: expectedString.characters.last, for example.
After dabbling in C# I'm now keen to use some OOP in Matlab - to date I've done none!
Let's say that I define a class for a data object with a handful of properties...
classdef TestRigData
properties
testTemperature
sampleNumber
testStrainAmplitude
sampleMaterial
rawData
end
methods
% Some constructors and data manipulation methods in here
end
end
...where 'rawData' would be a m-by-n array of actual experimental data, and the other values being doubles or strings to help identify each specific experiment.
If I have an array of TestRigData objects, what would be the best way of finding the indices of objects which meet specific criteria (e.g. testTemperature == 200)? Or getting all the unique values of a property (e.g. all the unique sample numbers in this collection).
If they were arrays of their own, (myNewArray = [3 5 7 22 60 60 5]) it would be easy enough using the find() and unique() functions. Is there a class I can inherit from here which will allow something like that to work on my object array? Or will I have to add my own find() and unique() methods to my class?
You can assign an ID value (a hash value in the general case) to TestRigData objects and store it as a new property. You can then extract all ID values at once to a cell array, e.g {yourarray.id} (or [yourarray.id] if the ID values are scalars), allowing you to apply find and unique with ease.
Adding your own find and unique is definitely possible, of course, but why make life harder? ;)
The suggestion of creating this as a handle class (rather than value class) is something I need to think about more in the future... after having put together some initial code, going back and trying to change classdef TestRigData to classdef TestRigData < handle seems to be causing issues with the constructor.
Bit unclear of how I would go about using a hash value unique to each object... but the syntax of extracting all values to an array is ultimately what got me in the right direction.
Getting a new object array which is the subset of the original big data array conforming to a certain property value is as easy as:
newObjectArray = oldObjectArray([oldObjectArray.testTemperature]==200);
Or for just the indices...
indicesOfInterest = find([oldObjectArray.testTemperature]==200);
Or in the case of non-scalar values, e.g. string property for sample material...
indicesOfInterest = find(strcmpi({oldObjectArray.sampleMaterial},'steel'));
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.