Equivalent of Swift Dotted Loop and Map in Objective C - ios

I have this code in swift
animation.keyTimes = (0...count).map {
NSNumber(value: CFTimeInterval($0) / CFTimeInterval(count))
}
I want to convert it into objective C. I am not sure how to use triple dot operator in objective C along with the map.
any help would be appreciated.

From docs:
The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.
So, i believe this should work fine:
NSMutableArray *result = [NSMutableArray array];
for (NSInteger i = 0; i <= count; i++) {
[result addObject: [NSNumber numberWithInteger:i]];
}
animation.keyTimes = result

This dot notation and mapping doesn't exist as first class citizens in Objective-C.
You could try Ranges (NSMakeRange(0, count);) and then enumerate the range.
Or you can write your own map function on a range or an array and use that.

... operator and .map method are available in swift only. So you can do it in objective-c like given below.
NSMutableArray *keyTimes = [NSMutableArray array];
for(int i = 0; i <= count; i++) {
[keyTimes addObject:[NSNumber numberWithInteger: CFTimeInterval(i)/CFTimeInterval(count)];
}
animation.keyTimes = keyTimes

There is no direct equivalent for the closed range operator and map in Objective-C.
An analogous translation is NSRange, NSIndexSet and enumerateIndexes...
NSInteger startIndex = 0;
NSInteger count = 100;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(startIndex, count + 1)];
__block NSMutableArray<NSNumber *> * keyTimes = [NSMutableArray array];
[indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
[keyTimes addObject: [NSNumber numberWithDouble: (double)idx / (double)count]];
}];
NSLog(#"%#", keyTimes);

Related

NSNumber in arrays, ios

I am trying to learn about how to put numbers into an array with nsnumber. The exact thing I'm stuck with is, To build the sequence in the array, we're going to need a loop. Between creating the sequence array and returning it, declare a for loop whose counter is limited by index + 1 and increments by one.
Since the sequence requires the two previous numbers to calculate the next one, we need to prime the sequence. We're going to need to manually pass in #0 and #1 on the first two iterations of the loop. This is what I have so far.
(NSArray *)arrayWithFibonacciSequenceToIndex:(NSUInteger)index
{
NSMutableArray *sequence = [NSMutableArray array];
for(NSUInteger i = 0; i < 1; i++)
{
index = i+1;
}
return sequence;
}
Am I on the right track? I'm not sure if my for loop is correct. Do I put sequence into the for loop and add the nsnumber #0 and #1 there or do I put those numbers into the sequence outside the loop?
To insert a number in an NSArray, you have to wrap them in a NSNumber:
NSInteger a = 5;
NSNumber number = #(a); // ou #5;
to perform mathematical operations on 2 NSNumbers, you have to convert them to integer (or double, float...) before
NSNumber * number1 = #1;
NSNumber * number2 = #6;
NSInteger sum = [number1 integerValue] + [number2 integerValue];
for the fib problem, youre loop is correct. The way I would think of this is : I add my value in the for loop, and if I'm adding the 1st or 2nd element, then I put a 0, else I sum the last 2 elements:
- (NSArray *) fibbonacciSequenceWithSize:(NSInteger)size
{
NSMutableArray * result = [NSMutableArray new];
for(NSInteger idx = 0; i < size ; i ++)
{
// first 2 numbers of fib sequence are 1
if(idx == 0 || idx == 1)
{
[result addObject:#1];
}
else
{
// Add the 2 previous number
// F2 = F1 + F0
NSinteger next = [result[idx - 2] integerValue] + [result[idx - 1] integerValue];
[result addObject:#(next)];
}
}
return [result copy]; // copy the NSMutableArray in a NSArray
}
You can clean up the code by having a Fibonacci function that provides the sum of the last two elements.
- (NSNumber *)nextFibInArray:(NSArray *)array {
if (array.count < 2) return #1;
NSInteger lastIndex = array.count - 1;
return #([array[lastIndex-1] intValue] + [array[lastIndex] intValue]);
}
Then the loop is cleaner, too.
- (NSArray *)fibonacciWithLength:(NSInteger)length {
NSMutableArray *result = [#[] mutableCopy];
for (NSInteger i=0; i<length; i++) {
[result addObject:[self nextFibInArray:result]];
}
return result;
}
We could trim some execution time fat from this, but for short enough sequences, this should be clear and quick enough.

How to save two Arrays in two dimensional Array?

I am new at iOS Dev. I want to save two different arrays (array1 & array2) in 2 dimensional array. I know how to save data directly in two dimensional array but can't by save two different arrays in one.
NSString* path = [[NSBundle mainBundle] pathForResource:#"Aasvogel" ofType:#"txt"];
NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSArray* foo = [content componentsSeparatedByString: #","];
NSMutableArray *array1 = #[], *array2 = #[];
for ( int i = 0; i < [foo count]; i++ )
{
NSString* day = foo[i];
if ( i % 2 == 0 ) { [array1 addObject:day];}
else { [array2 addObject:day];}
}
// and here i have populated two arrays (array1 and array2)
// Now i want to save these arraya in below two dimensional array (dataArray) atIndex:0 and at Index:1
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithCapacity: 2];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"e",
#"el",
#"ale",
#"vela",
#"gavel",nil] atIndex:0];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"Represents 50 in Roman numeral",
#"Building Wing",
#"Pub Brew",
#"Thin Parchment or membranes",
#"chairperson's hammer",nil] atIndex:1];
I have recently implemented 2D array into my application. Please check below code which is available at 2DArray
int capacity;
#property (nonatomic, strong) NSMutableArray *outerArray;
#define kCRL2DArrayEmptyKey #"kCRL2DArrayEmptyKey"
- (id) initWithRows:(int)x columns:(int)y
{
if (self = [super init])
{
capacity = y;
self.outerArray = [NSMutableArray array];
for (int i = 0; i < x; i++) {
NSMutableArray *innerArray = [NSMutableArray array];
for (int j = 0; j < y; j++) {
[innerArray addObject:kCRL2DArrayEmptyKey];
}
[self.outerArray addObject:innerArray];
}
}
return self;
}
you can try this
NSArray * firstArray, *secondArray;
NSArray * mainArray= [[NSArray alloc]initWithObjects: firstArray, secondArray, nil];
I am not sure about 2-dimensional array in iOS but if I were you I would be saved the two arrays within a dictionary such as
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setvalue:yourArray forKey:#"FirstArray"];
[dict setvalue:yourSecondArray forKey:#"SecondArray"];
And Use it accordingly.
There’s no such thing as a two (or more) dimensional NSArray. If you genuinely need an n-dimensional array object in iOS or OS X, you can of course roll your own, or you could instead create an NSArray of NSArray instances (which are columns and which are rows is entirely up to you). In that case, you could e.g. add items by doing
[[outerArray objectAtIndex:0] addObject:#"Foo"];
[[outerArray objectAtIndex:1] addObject:#"Bar"];
That said, for the problem you are tackling, it looks to me as if an NSDictionary might be more appropriate, e.g. with keys #"e", #"el" and values #"Represents 50 in Roman numerals", #"Building Wing".
If your concern is that the keys of NSDictionary are not held in sorted order, you can always extract the keys as an array and sort them. Or, if the keys change regularly, you might want to use a more sophisticated approach (e.g. keeping a separate sorted array of keys and inserting them into the right place when adding to the NSDictionary).
Also, you know that in modern Objective-C you can write e.g.
#[ #"a", #"b", #"c" ]
or
#{ #"a": #1, #"b": 2 }
rather than the very verbose forms you're using above?
this is how u add anything in a 2d array i.e an Array of arrays in objective-c
NSMutableArray *array 1 = [[NSMutableArray alloc]init];
NSMutableArray *array 2;
for(int col = 0;col <5;col++){
array2 = [[NSMutableArray alloc]init];
for(int row = 0;row<5;row++){
[array2 addObject:myItems];
}
[array1 addObject:array2];
}
hope this helps
use for loop to generate 2d array from 2 different array,
follow this stracture
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncolumns; j++)
array[i][j] = 0;
}
}
May be it will help you

NSMutableArray with int values from 1 to 100

This should be dead easy, but somehow it doesn't want to work for me. Using iOS 7 and XCode 5.
All I'm trying to do is create an array with values from 1 to 100.
NSMutableArray *array;
for (int i = 0; i < 100; i++)
{
[array addObject:i];
}
This doesn't work. I get a "Implicit conversion of 'int' to 'id' is disallowed with ARC.
I get it, I can't add primitive types to an NSMutableArray.
[array addObject:#i];
This doesn't work either. I get a "unexpected '#' in program"
[array addObject:[NSNumber numberWithInt:i]];
[array addObject:[NSNumber numberWithInteger:i]];
(either case) This "works" (compiles) but it really doesn't "work". The problem with this is that the value from NSNumber is really not a 1-100. What I get for each row is "147212864", 147212832", "147212840"...not what I want.
Lastly:
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
{
[array addObject:i];
}
This also doesn't compile. I get an error on the i++. "Arithmetic on pointer to interface 'NSNumber', which is not a constant size for this architecture and platform"
Any suggestions on how to do this extremely simple thing on obj-c?
Either one of these should work:
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
or
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:[NSNumber numberWithInt:i]];
}
Here are the reasons why your code snippets did not work:
[array addObject:i] - You cannot add primitives to Cocoa collections
[array addObject:#i] - You forgot to enclose the expression i in parentheses
NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++ - You cannot increment NSNumber without "unwrapping" its value first.
If memory serves, I think you're simply missing parenthesis around the NSNumber shorthand expression.
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < 100; i++)
{
[array addObject:#(i)];
}
Minimally, #i should be #(i) as described here. You are also forgetting to allocate and initialise your array
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
And since you are getting: "147212864", 147212832", "147212840"...not what I want., I think you are probably printing out your information wrongly or because the array is unallocated, that's simply garbage. Can you show us how you are outputting?
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *myNum;
for (int i = 0; i < 100; i++) {
myNum = [[NSNumber alloc]initWithInt:i];
[array addObject:myNum];
}
NSLog(#"%#", array); // 1 - 99 as expected
Worked for me :)
Just saying: Turn on all reasonable warnings in your Xcode project. Then read what the warnings are saying and do something about them. When you write something like
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
What does a for loop do? An object is in the end a pointer. So you initalise i to nil. Then you compare a pointer with a random pointer: [NSNumber numberWithInteger:100] returns a pointer to an object which could be anywhere in memory, and you compare pointers. Next the i++: No, you can't increment a pointer to an NSNumber. It doesn't make sense.

Insert an object into NSMutable array and shift element one position ahead iOS

I want to insert an object (say 1.5) into NSMutableArray (say array with content: 1,2,3,4) between 1 and 2. The resultant array would be one element greater (say 1,1.5,2,3,4).
How can this be acheived in iOS using NSMutableArray?
Assuming you know the index to insert at, just use NSMutableArray's insertObject:atIndex: (reference). In your case, you want:
[yourMutableArray insertObject:#(1.5) atIndex:1];
If you don't know the index, you can do something like this (copy-pasted because nobody likes broken links):
#implementation NSMutableArray (SelfSorting)
- (void)insertNumberAtSortedLocation:(NSNumber *)aNumber
{
NSUInteger count = [self count];
// if there are no contents yet, simply add it
if (!count)
{
[self addObject:aNumber];
return;
}
NSRange searchRange;
searchRange.location = 0;
searchRange.length = count;
// bubble sort finding of insert point
do
{
NSInteger index = searchRange.location + searchRange.length/2;
NSNumber *testNumber = [self objectAtIndex:index];
switch ([aNumber compare:testNumber])
{
case NSOrderedAscending:
{
//searchRange.length = searchRange.length / 2;
searchRange.length = index - searchRange.location;
break;
}
case NSOrderedDescending:
{
int oldLocation = searchRange.location;
searchRange.location = index+1;
searchRange.length = searchRange.length - (searchRange.location - oldLocation);
break;
}
case NSOrderedSame:
{
searchRange.length = 0;
searchRange.location = index;
break;
}
}
} while (searchRange.length>0);
// insert at found point
[self insertObject:aNumber atIndex:searchRange.location];
}
And then, call:
[yourMutableArray insertNumberAtSortedLocation:#(1.5)];
Two lines of code
Just append the item and then sort or sort at usage time, sorting is actually very cheap, almost O(n) for non pathological cases.
NSMutableArray *a = [#[#1, #2 ,#3 ,#4] mutableCopy];
// Two lines of code:
[a addObject:#(1.5)];
[a sortUsingSelector:#selector(compare:)];
NSLog(#"a: %#", a);
NSLog oputput:
a: (
1,
"1.5",
2,
3,
4
)
The above should be O(log n)
Or if you don't want the entire array sorted, just insert after the first entry that is less than it:
NSUInteger count = [a count];
int index = 0;
while (index < count && [a[index] compare:aNumber] == NSOrderedAscending) {
index += 1;
}
[a insertObject:aNumber atIndex:index];
The above is O(n) as opposed to a binary search which is O(log n) but for most arrays there is not a meaningful time difference.
For the example in your question, you would write [array insertObject:#(1.5) atIndex:1]
NSMutableArray * foo = [[NSMutableArray alloc] init];
[foo insertObject:<#(id)#> atIndex:<#(NSUInteger)#>]

converting a onedimensional array to 2-d array having the specified number of columns

i am passing one one dimensional array having elements "1,2,3,4,5,6,7"
and in my code i want to convert this array into a 2-dimensional array .
The number of columns of the 2-d array will be specified by user .
say if am setting the columns value to 3
then the output 2-d array should be in the format
123
456
7
.m file of my class
-(NSMutableArray *)OneToTwoDimensionalArray:(NSMutableArray *)values :(NSInteger)columns
{
NSMutableArray * twoDimensional=[[NSMutableArray alloc]initWithCapacity:columns];
for(int i=0;i<columns;i++)
{
[twoDimensional insertObject:values atIndex:i];
}
return twoDimensional;
}
viewcontroller.m file
EPArray *arr=[[EPArray alloc]init];
int columns=4;
arr1=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7",nil];
NSMutableArray *finalresult=[arr OneToTwoDimensionalArray:arr1 :columns];
for(int i=0;i<columns;i++)
{
NSLog(#"%#",[finalresult objectAtIndex:i]);
}
Try this,
NSArray *array = #[#"1", #"2", #"3", #"4", #"5", #"6", #"7"];
int noOfColumns = 3;
NSMutableArray *outerArray = [[NSMutableArray alloc] init];
for (int counter = 0; counter < [array count]; counter = counter + noOfColumns) {
NSMutableArray *innerArray = [[NSMutableArray alloc] init];
for (int arrayIndex = counter; ((arrayIndex < counter + noOfColumns) && (arrayIndex < [array count])); arrayIndex++) {
[innerArray addObject:array[arrayIndex]];
}
[outerArray addObject:innerArray];
}
NSLog(#"outerArray = %#", outerArray);
Here outerArray will give the 2 dimensional array with the provided column value. The above code is readable and easy to maintain especially if you want to make some quick changes.
Output:
outerArray = (
(
1,
2,
3
),
(
4,
5,
6
),
(
7
)
)
Next to my other answer — that I would favor — I want to offer another solution, that uses more traditional C-style programming but is quite readable.
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *newArray = [NSMutableArray array];
NSUInteger columnIdx = 0;
for (NSUInteger count = 0; count < [array count]; ++count) {
if (columnIdx == 0) {
[newArray addObject:[NSMutableArray array]];
}
NSMutableArray *lastArray = [newArray lastObject];
[lastArray addObject:array[count]];
columnIdx = (++columnIdx)%columnWidth;
}
newArray now contains the subarrays as required.
note, that also this solution uses the modulo operator columnIdx = (++columnIdx)%columnWidth;.
instead of this you also could write
++columnIdx;
if(columnIdx == columnWidth) columnIdx = 0;
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *mArray =[NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % columnWidth == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
mArraynow contains 3 arrays with
(
(
1,
2,
3
)
,
(
4,
5,
6
)
,
(
7
)
)
This code uses the modulo operator that finds the remainder of division of one number by another.
if (idx % 3 == 0) {
[mArray addObject:[NSMutableArray array]];
}
if there is no remainder, it must be the index 0,3,6,…. In such a case, a new array is added to the outer array. the object are always added to the last array.
Also note that using enumerateObjectsUsingBlock: should be faster than using c-style for (for(int i=0;i<columns;i++)) or even fast enumeration.
I added a second answer that uses only C-constructs rather than blocks, but I'd favor this one.
and — of course — you should consider using a category on NSArray
#interface NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width;
#end
#implementation NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width
{
NSAssert(width > 0, #"width need to be 1 or greater");//sanity check
NSMutableArray *mArray =[NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % width == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
return mArray;
}
#end
You would use it like:
NSArray *numbers = [#[#1, #2, #3, #4 ,#5, #6, #7] arrayOfArraysWithColumnWidth:3];

Resources