split NSArray in groups of smaller NSArrays for paging - iphone

I have an NSArray of say 100 NSManagedObjects and I need to split that into an NSArray that contains 10 NSArray objects that each hold 10 of theses NSManagedObjects, how would I accomplish that?
I am going to do some paging and this will work well for me.

How are you getting these NSManagedObjects? If you're using an NSFetchRequest, you may want to keep that around and only get 10 results at a time from it.

Here is my code:
[object splitArrayWithArray:arrayWith100Objects rangeNumber:10];
- (NSArray*) splitArrayWithArray:(NSArray*)rawArray rangeNumber:(int)rangeNumber{
int totalCount = rawArray.count;
int currentIndex = 0;
NSMutableArray* splitArray = [NSMutableArray array];
while (currentIndex<totalCount) {
NSRange range = NSMakeRange(currentIndex, MIN(rangeNumber, totalCount-currentIndex));
NSArray* subArray = [rawArray subarrayWithRange:range];
[splitArray addObject:subArray];
currentIndex +=rangeNumber;
}
return splitArray;
}

Something along these lines should work instead of breaking it into separate arrays
//make a new range for each page
NSRange myRange = NSMakeRange(10, 10);
NSArray * myArray = [NSArray array];
//...pass both into a function
for (int i = myRange.location; i < myRange.location + myRange.length; i++) {
//stuff with the array elements
[[myArray objectAtIndex:i] doSomething];
}

It's no one-liner, but this will split an array into pages:
NSArray *arrayToSplit = ...
int pageSize = 50;
NSMutableArray *arrayOfPages = [NSMutableArray new];
NSRange range = NSMakeRange(0, pageSize);
while (range.location < arrayToSplit.count) {
if (range.location + range.length >= arrayToSplit.count)
range.length = arrayToSplit.count - range.location;
[arrayOfPages addObject:[arrayToSplit objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range]]];
range.location += range.length;
}

Related

iOS Search Results Order

I have a UISearchBar that searches a table of data. When a search is typed in, the results are displayed in an order like so:
Starts typing 'ch...'
1. Ache
2. Cherries
3. Choice
It makes more sense to me (and for my app) that 'Cherries' and 'Choice' would be at the top of the results, because 'ch' and not 'ach' was typed in. Is this something that can be changed programatically, or is it just the way iOS searches work?
You have to give the search option as NSAnchoredSearch
NSRange searchRange = [sortedString rangeOfString:searchText options:NSAnchoredSearch];
Some of the search method listed below
NSCaseInsensitiveSearch
NSLiteralSearch
NSBackwardsSearch
NSAnchoredSearch
NSNumericSearch
NSDiacriticInsensitiveSearch
NSWidthInsensitiveSearch
NSForcedOrderingSearch
NSRegularExpressionSearch
Eg:
- (void)search {
NSString *searchText = [searchBar.text lowercaseString];
for (int index = 0; index < [availableCollectionArray count]; index++) {
NSArray *tempArray = [availableCollectionArray objectAtIndex:index];
for (int tempIndex = 0; tempIndex < [tempArray count] ; tempIndex++) {
NSString *sortedString = [tempArray objectAtIndex:tempIndex];
NSRange searchRange = [sortedString rangeOfString:searchText options:NSAnchoredSearch];
if (searchRange.length > 0)
{
[sortedArray addObject: sortedString]; //add the string which starts from searchBar.text
}
}
}
}

Better way to handle arrays in Objective-C?

Please let me preface this question with an apology. I am very new to Objective C. Unfortunately, I have a very tight timeline on a project for work and need to get up to speed as fast as possible.
The code below works. I am just wondering if there is a better way to handle this... Maybe something more Cocoa-ish. The entire purpose of the function is to get an ordered list of positions in a string that have a certain value.
I fell back on a standard array for comfort reasons. The NSMutableString that I initially declare is only for testing purposes. Being a complete noob to this language and still wrapping my head around the way Objective C (and C++ I guess) handles variables and pointers, any and all hints, tips, pointers would be appreciated.
NSMutableString *mut = [[NSMutableString alloc] initWithString:#"This is a test of the emergency broadcast system. This is only a test."];
NSMutableArray *tList = [NSMutableArray arrayWithArray:[mut componentsSeparatedByString:#" "]];
int dump[(tList.count-1)];
int dpCount=0;
NSUInteger length = [mut length];
NSRange myRange = NSMakeRange(0, length);
while (myRange.location != NSNotFound) {
myRange = [mut rangeOfString:#" " options: 0 range:myRange];
if (myRange.location != NSNotFound) {
dump[dpCount]=myRange.location;
++dpCount;
myRange = NSMakeRange((myRange.location+myRange.length), (length - (myRange.location+myRange.length)));
}
}
for (int i=0; i < dpCount; ++i) {
//Going to do something with these values in the future... they MUST be in order.
NSLog(#"Dumping positions in order: %i",dump[i]);
}
text2.text = mut;
[mut release];
Thanks again for any replies.
There is not great way to do what you are trying to do. Here is one way:
// locations will be an NSArray of NSNumbers --
// each NSNumber containing one location of the substring):
NSMutableArray *locations = [NSMutableArray new];
NSRange searchRange = NSMakeRange(0,string.length);
NSRange foundRange;
while (searchRange.location < string.length) {
searchRange.length = string.length-searchRange.location;
foundRange = [string rangeOfString:substring options:nil range:searchRange];
if(foundRange.location == NSNotFound) break;
[locations addObject:[NSNumber numberWithInt:searchRange.location]];
searchRange.location = foundRange.location+foundRange.length;
}
This might be a little more streamlined (and faster in terms of execution time, if that matters):
const char *p = "This is a test of the emergency broadcast system. This is only a test.";
NSMutableArray *positions = [NSMutableArray array];
for (int i = 0; *p; p++, i++)
{
if (*p == ' ') {
[positions addObject:[NSNumber numberWithInt:i]];
}
}
for (int j = 0; j < [positions count]; j++) {
NSLog(#"position %d: %#", j + 1, [positions objectAtIndex:j]);
}

How to Find Duplicate Values in Arrays?

I am working on SQLite and I have written a query which returns me two arrays ItemsArray and CustomersIDArray as:
ItemsArray
Element at Index 0 = Off White,
Element at Index 1 = Fan,
Element at Index 2 = Off White,
Element at Index 3 = Delux,
Element at Index 4 = Fan
CustomerIDArray
Element at Index 0 = 1,
Element at Index 1 = 2,
Element at Index 2 = 2,
Element at Index 3 = 3,
Element at Index 4 = 4
I want result like that Off White = 2 (count) , Fan = 2 (count) and Delux = 1;
and the Resultant Array,
Result Array
Element at Index 0 = Off White,
Element at Index 1 = Fan,
Element at Index 2 = Delux
Actually I want the count of repetition in first array but the value must not same for CustomerArray.
Please help me through logic or code.
-(NSMutableArray *)getCountAndRemoveMultiples:(NSMutableArray *)array{
NSMutableArray *newArray = [[NSMutableArray alloc]initWithArray:(NSArray *)array];
NSMutableArray *countArray = [NSMutableArray new];
int countInt = 1;
for (int i = 0; i < newArray.count; ++i) {
NSString *string = [newArray objectAtIndex:i];
for (int j = i+1; j < newArray.count; ++j) {
if ([string isEqualToString:[newArray objectAtIndex:j]]) {
[newArray removeObjectAtIndex:j];
countInt++;
}
}
[countArray addObject:[NSNumber numberWithInt:countInt]];
countInt = 1;
}
NSMutableArray *finalArray = [[NSMutableArray alloc] initWithObjects:newArray, countArray, nil];
NSLog(#"%#", finalArray);
return finalArray;
}
- (IBAction)getArrayInfo:(id)sender {
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:#"Off White", #"Fan", #"Off White", #"Deluxe", #"Fan", nil];
NSMutableArray *godArray = [self getCountAndRemoveMultiples:myArray];
NSLog(#"Array from this end = %#", godArray);
}
I just set up -getArrayInfo to test it out. Works fine. As you can see, the array you want to display will be at index:0, and the countArray at index:1.
Use NSCountedSet like below
NSMutableArray *ary_res = [[NSMutableArray alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"11",#"13",#"34",#"9",#"13",#"34",#"9",#"2",nil];
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:array];
for(id name in set)
{
if([set countForObject:name]==2)
[ary_res addObject:name];
}
//
NSLog(#"%#",ary_res);
try this:
NSArray *copy = [ItemsArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([ItemsArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[ItemsArray removeObjectAtIndex:index];
}
index--;
}

How to sort an array with alphanumeric values?

I have an array which contains strings like frame_10#3x.png , frame_5#3x.png,frame_19#3x.png etc.
So I want to sort this array according to the number after the underscore i.e. the correct sequence will be frame_5#3x.png,frame_10#3x.png,frame_19#3x.png.
I tried to use the following method but no result:
NSInteger firstNumSort(id str1, id str2, void *context) {
int num1 = [str1 integerValue];
int num2 = [str2 integerValue];
if (num1 < num2)
return NSOrderedAscending;
else if (num1 > num2)
return NSOrderedDescending;
return NSOrderedSame;
}
Please suggest how to do this sorting for array.
NSArray *sry_img = [[NSArray alloc] initWithObjects:#"frame_18#3x.png",#"frame_17#3x.png",#"frame_1222#3x.png",#"frame_10#3x.png",#"frame_3#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",#"frame_1#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",nil];
NSArray *sortedStrings = [sry_img sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
NSLog(#"%#",sortedStrings);
Enjy .......
But
localizedStandardCompare:, added in 10.6, should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method may be tweaked in future releases, and will be different under different localizations, so clients should not depend on the exact sorting order of the strings.
you want to do something like:
NSArray *components1 = [str1 componentsSeparatedByString:#"_"];
NSArray *components2 = [str2 componentsSeparatedByString:#"_"];
NSString *number1String = [components1 objectAtIndex:([components1 count] - 1])];
NSString *number2String = [components2 objectAtIndex:([components2 count] - 1])];
return [number1String compare:number2String];
I am not sure if my solution is the best possible approach but it can solve your problem for the time being :) .
1) First I have written a function to get the numbers before # character in your string and then I implemented simple SELECTION SORT algo to sort the array using this functions.
- (NSString*)getSubStringForString:(NSString*)value {
// First we will cut the frame_ string
NSMutableString *trimmedString = [NSMutableString stringWithString:[value substringWithRange:NSMakeRange(6, [value length]-6)]];
// New String to contain the numbers
NSMutableString *newString = [[NSMutableString alloc] init];
for (int i = 0; i < [trimmedString length] ; i++) {
NSString *singleChar = [trimmedString substringWithRange:NSMakeRange(i, 1)];
if (![singleChar isEqualToString:#"#"]) {
[newString appendString:singleChar];
} else {
break;
}
}
return newString;
}
This is the selection Implementation of the algo for sorting. The main logic is in the for loop. You can copy the code in viewDidLoad method to test.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"frame_10#3x.png",#"frame_5#3x.png",
#"frame_3#3x.png", #"frame_19#3x.png",
nil];
NSLog(#"Values before Sort: %#", array);
int iPos;
int iMin;
for (iPos = 0; iPos < [array count]; iPos++)
{
iMin = iPos;
for (int i = iPos+1; i < [array count]; i++)
{
if ([[self getSubStringForString:[array objectAtIndex:i]] intValue] >
[[self getSubStringForString:[array objectAtIndex:iMin]] intValue]) {
iMin = i;
}
}
if ( iMin != iPos )
{
NSString *tempValue = [array objectAtIndex:iPos];
[array replaceObjectAtIndex:iPos withObject:[array objectAtIndex:iMin]];
[array replaceObjectAtIndex:iMin withObject:tempValue];
}
}
NSLog(#"Sorted Values: %#", array);
I hope that it can atleast keep you going. :)
You can try this-
NSString *str1 = [[[[str1 componentsSeparatedByString:#"frame_"] objectAtIndex:1] componentsSeparatedByString:#"#3x.png"] objectAtIndex:0];
int num1 = [str1 integerValue];

What is an easy way to break an NSArray with 4000+ objects in it into multiple arrays with 30 objects each?

What is an easy way to break an NSArray with 4000 objects in it into multiple arrays with 30 objects each?
So right now I have an NSArray *stuff where [stuff count] = 4133.
I want to make a new array that holds arrays of 30 objects. What is a good way to loop through, breaking *stuff into new 30-object arrays, and placing them inside of a larger array?
Obviously the last array won't have 30 in it (it will have the remainder) but I need to handle that correctly.
Make sense? Let me know if there is an efficient way to do this.
Off the top of my head, something like (untested):
NSMutableArray *arrayOfArrays = [NSMutableArray array];
int itemsRemaining = [stuff count];
int j = 0;
while(itemsRemaining) {
NSRange range = NSMakeRange(j, MIN(30, itemsRemaining));
NSArray *subarray = [stuff subarrayWithRange:range];
[arrayOfArrays addObject:subarray];
itemsRemaining-=range.length;
j+=range.length;
}
The MIN(30, i) takes care of that last array that won't necessarily have 30 items in it.
NSMutableArray *arrayOfArrays = [NSMutableArray array];
int batchSize = 30;
for(int j = 0; j < [stuff count]; j += batchSize) {
NSArray *subarray = [stuff subarrayWithRange:NSMakeRange(j, MIN(batchSize, [stuff count] - j))];
[arrayOfArrays addObject:subarray];
}
Converted the answer of #samvermette to SWIFT 3
var arrayOfArraySlices = [ArraySlice<CBOrder>]() // array of array slices
var itemsRemaining = orderArray.count
var j = 0
while itemsRemaining > 0 {
let range = NSRange(location: j, length: min(20, itemsRemaining));
let arraySlice = orderArray[range.location..<range.location + range.length]
arrayOfArraySlices.append(arraySlice)
itemsRemaining -= range.length;
j += range.length;
}