Matlab - sort cell array of objects by property - matlab

Suppose I had a class named Foo, with a datenum property named DateTime. If I had a cell array collection of Foo objects, how would I sort that according to each object's DateTime property?
I have seen references to overloading the sort method and working with arrays of objects, however I'm using a cell array due to dynamic sizing and those instructions aren't holding up. Anybody got some suggestions? Cheers

The simplest approach is to extract the time-values into a vector, sort that, and use the new order to sort the original array.
%# extract DateTime from the cell array fooCell
dateTime = cellfun(#(x)x.DateTime, fooCell);
[~,sortIdx] = sort(dateTime);
%# reorder fooCell
fooCell = fooCell(sortIdx);

Related

Finding an object with a certain property value in an array of objects in MatLab?

I have a class as follows
class Car
properties
index
price
color
end
end
I created an array of these objects and added several cars to the array. All cars have a unique index. Now I want to find the car in this array with the index 5. How can I do this?
You can do this one of two ways:
Create an array from the indices and then compare against 5 to yield a logical array that you can then use to index into your array to grab the ones that meet the criteria.
item = obj_array([obj_array.index] == 5)
Use findobj to locate an object in an array with a particular property/value pair (note that this only works if you are using a handle class and not a value class)
item = findobj(obj_array, 'index', 5)

find value in a string of cell considering some margin

Suppose that I have a string of values corresponding to the height of a group of people
height_str ={'1.76000000000000';
'1.55000000000000';
'1.61000000000000';
'1.71000000000000';
'1.74000000000000';
'1.79000000000000';
'1.74000000000000';
'1.86000000000000';
'1.72000000000000';
'1.82000000000000';
'1.72000000000000';
'1.63000000000000'}
and a single height value.
height_val = 177;
I would like to find the indices of the people that are in the range height_val +- 3cm.
To find the exact match I would do like this
[idx_height,~]=find(ismember(cell2mat(height_str),height_val/100));
How can I include the matches in the previous range (174-180)?
idx_height should be = [1 5 6 7]
You can convert you strings into an numeric array (as #Divakar mentioned) by
height = str2num(char(height_str))*100; % in cm
Then just
idx_height = find(height>=height_val-3 & height<=height_val+3);
Assuming that the precision of heights stays at 0.01cm, you can use a combination of str2double and ismember for a one-liner -
idx_height = find(ismember(str2double(height_str)*100,[height_val-3:height_val+3]))
The magic with str2double is that it works directly with cell arrays to get us a numeric array without resorting to a combined effort of converting that cell array to a char array and then to a numeric array.
After the use of str2double, we can use ismember as you tried in your problem to get us the matches as a logical array, whose indices are picked up with find. That's the whole story really.
Late addition, but for binning my first choice would be to go with bsxfun and logical operations:
idx_height = find(bsxfun(#le,str2double(height_str)*100,height_val+3) & ...
bsxfun(#ge,str2double(height_str)*100,height_val-3))

Look for multiple values in a cell array at the same time in Matlab

I have CellArray1 with 50 unique strings and CellArray2 with 2000 unique strings (50 of which are the same as the ones in CellArray1). Is there a way to find the positions of all 50 unique strings from the first cell array in the second cell array without using loops?
Yes - the following code demonstrates this:
cellArray1 = {'hello', 'world'};
cellArray2 = {'good', 'morning', 'world'};
overlap = find(ismember(cellArray2, cellArray1)};
This will return the value 3 in overlap since cellArray2{3} appears in cellArray1.
UPDATE
The above code returns the indices, but not in the order of the original. If you need the original order, you can do the following
overlap = cellfun(#(x)find(ismember(cellArray2, x)), cellArray1, 'uniformOutput', false);
overlapSorted = cell2mat(overlap);
It could be argued that cellfun actually has an implicit loop in it (but then all vector operations have implicit loops, really); but one of these constructions will do what you asked for. If you don't need it sorted, the first will be significantly faster, I imagine.

iphone - Create NSMutableDictionary filled with NSMutableArrays dynamically

I have an array of objects. Each object has property "date" and "title".
I want to populate sectioned UITableView with those items like:
Section 1 - 2012.06.12 (taken from object.date)
Cell 1.1: Title 1 (taken from object.name)
Cell 1.2: Title 2
Cell 1.3: Title 3
...
Section 2 - 2012.06.13
Cell 2.1: Title 1
Cell 2.2: Title 2
..
Section 3 ..
I can do that by manually creating 1..n NSMutableArrays for all date combinations and filling them with object.name values. But the problem is I do not know how many date combinations there are, so it should be done dynamically. Also, the date property can repeat in different objects
My object structure is:
Object
-NSDate - date
-NSString - title
UPD:
I was thinking if it is possible to create NSDictionary, where the key would be my date and the object would be NSArray, which contains all my items for the key-date. But I do not know how to do that dynamically.
I hope I explained my question clearly enough.
Thank you in advance!
You can create arrays based on date.You have array of objects, so iterate through this array of objects to get distinct dates, as follows:
for(int i =0;i<[objectsArr count];i++)
{
if(![newDateArr containsObject:[objectsArr objectAtIndex:i].date])
{
[newDateArr addObject:[objectsArr objectAtIndex:i].date];
}
NSMutableArray *newTitleArray = [newTitleDictionary objectForKey:#"[objectsArr objectAtIndex:i].date"];
if(newTitleArray != nil)
{
[newTitleArray addObject:[objectsArr objectAtIndex:i].title];
}
else
{
newTitleArray = [[[NSMutableArray alloc] init] autorelease];
[newTitleArray addObject:[objectsArr objectAtIndex:i].title];
}
[newTitleDictionary setValue:newTitleArray forKey:#"[objectsArr objectAtIndex:i].date"];
}
where newTitleDictionary and newDateArr are declare outside this method.Now you can use both is newTitleDictionary and newDateArr to populate tableview.
If I understand you correctly, you want to put an object into an array and then use that array to populate a table view?
Just add the date object each time to the NSMutableArray.
[myArray addObject:dateObject];
Then when it comes to populating the table view..
DateObject *newDateObj = [myArray objectAtIndex:index];
I hope this helps and I understood your question
EDIT To answer now I understand a bit more.
Step 1
Check through the existing array of dates and see if there are any that match maybe by iterating through it using a for loop. Search online for how to compare NSDate.
Step 2 If it doesn't match any then insert it into the array as an array with just that date on it's own so the array count will be one. If it does match then insert it into the array along with that one making the array count 2 or more.
Step 3 When it comes to declaring the section amount for the table just return the dateHolderArray count.
Step 4 When declaring the amount of rows in each section, return the array count for the array thats inside the dateHolderArray.
Step 5 Display the content when it comes to populating the cells with information. It becomes just a task of getting the dates from the arrays using the section ids and row ids.
This is how I would do it, there are probably many other methods. Any questions just ask

Objective-C, How can I produce an array / list of strings and count for each?

My aim is to produce an array, which I can use to add section headers for a UITableView. I think the easiest way to do this, is to produce a sections array.
I want to create section headers for dates, where I'll have several or no rows for each.
So in my populate data array function, I want to populate a display array. So record 1, look for the first date in my display array, create a new array item if it doesn't exist, if it does exist add 1 to the count.
So I should end up with something like this.
arrDisplay(0).description = 1/June/2001; arrDisplay(0).value = 3;
arrDisplay(1).description = 2/June/2001; arrDisplay(1).value = 0;
arrDisplay(2).description = 3/June/2001; arrDisplay(2).value = 1;
arrDisplay(3).description = 5/June/2001; arrDisplay(3).value = 6;
My question is how do I create and use such an array with values, where I can add new elements of add to the count of existing elements and search for existing elements ?
I think, if i understand you, an NSMutableDictionary would work. (as NR4TR said) but, i think the object would be the description and the key would be the count. you could check for the key and get the count in the same gesture. if the return value of objectForKey is nil, it doesn't exist.
NSMutableDictionary *tableDictionary = [[NSMutableDictionary alloc] init];
NSString *displayKey = #"1/June/2001";
NSNumber *displayCount = [tableDictionary objectForKey:displayKey];
if (displayCount != nil) {
NSNumber *incrementedCount = [[NSNumber alloc] initWithInteger:[displayCount integerValue] + 1];
[tableDictionary removeObjectForKey:displayKey];
[tableDictionary setValue:incrementedCount
forKey:displayKey];
[incrementedCount release];
}
else {
NSNumber *initialCount = [[NSNumber alloc] initWithInteger:1];
[tableDictionary setValue:initialCount
forKey:displayKey];
[initialCount release];
}
EDIT: Hopefully this isn't pedantic, but I think a couple pointers will help.
Dictionaries, Sets, and Arrays all hold objects for retrieval. The manner of holding and retrieval desired drives the decision. I think of it based on the question 'what is the nature of the information that I have when I need an object being held?'
NSDictionary and NSMutableDictionary
Hold n objects per key. (I think...I haven't had to test a limit, but i know you can get an NSSet back as a value.)
KEY is more important than INDEX. I don't think of dictionaries as ordered. they know something and you need to ask the correct question.
NSArray and NSMutableArray
hold n objects in order.
INDEX is most important bit of information. (you can ask for the index of an object but, even here, the index is the important part)
you will typically drive table views with an array because the ordered nature of the array fits.
NSSet, NSMutableSet, and NSCountedSet
A collection of objects without order.
You can change any of these into the other with something like [nsset setFromArray:myArray];
and all of these things can hold the other as objects. I think an array as your top level is the correct thinking, but beyond that, it becomes an issue of implementation
Try array of dictionaries. Each dictionary contains two objects - section title and array of section rows.
If you want to have a description AND a rowcount then you can either create a class with those two properties and generate an NSArray of objects with that class or instead of all that you can just use an NSDictionary to store key/value lookups.
I think NSCountedSet is closest to what you want. It doesn't have an intrinsic order, but you can get an array out of it by providing a sort order.