Objective-C Split an array into two separate arrays based on even/odd indexes

给你一囗甜甜゛ 提交于 2019-12-11 03:51:08

问题


I have an array, NSMutableArray *stringArray that looks like this

stringArray = 

[0]String1
[1]String2
[2]String3
[3]String4
[4]String5
[5]String6

How would I go about splitting this array into two arrays based on even/odd indexes?

Example:

NSMutableArray *oddArray = ([1], [3], [5]);

NSMutableArray *evenArray = ([0], [2], [4]);

Thanks in advance!


回答1:


There are following ways you can achieve that:-

The first and second one solution are already mentioned by the above two. Below are the implementation of the same:-

//First Solution
NSArray *ar=@[@"1",@"2",@"3",@"4",@"5"];
NSMutableArray *mut1=[NSMutableArray array];
NSMutableArray *mut2=[NSMutableArray array];
[ar enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    if (idx%2==0)
    {
        [mut1 addObject:object];
    }
    else
    {
        [mut2 addObject:object];
    }
}];

//Second Solution
NSMutableIndexSet *idx1 = [NSMutableIndexSet indexSet];
NSMutableIndexSet *idx2 = [NSMutableIndexSet indexSet];
for (NSUInteger index=0; index <ar.count(); index++)
{
   if(index%2==0)
    {
        [idx1 addIndex:index];
    }
    else{
        [idx2 addIndex:index];
    }
}
NSArray *evenArr=[ar objectsAtIndexes:idx1];
NSArray *oddArr=[ar objectsAtIndexes:idx2];
NSLog(@"%@",evenArr);
NSLog(@"%@",oddArr);



回答2:


create two mutable arrays, use enumerateObjectsWithBlock: on the source array and check idx % 2 to put it into first or second array

Using the ternary operator:

NSArray *array = @[@1,@2,@3,@4,@5,@6,@7,@8,@9,@10,@11,@12];
NSMutableArray *even = [@[] mutableCopy];
NSMutableArray *odd = [@[] mutableCopy];
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    NSMutableArray *evenOrOdd = (idx % 2) ? even : odd;
    [evenOrOdd addObject:object];
}];

If you like super compact code you could use the ternary operator like

[((idx % 2) ? even : odd) addObject:object];

If you want to split the array to N arrays, you can do

NSArray *array = @[@1,@2,@3,@4,@5,@6,@7,@8,@9,@10,@11,@12];

NSArray *resultArrays = @[[@[] mutableCopy],
                          [@[] mutableCopy],
                          [@[] mutableCopy]];

[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
        [resultArrays[idx % resultArrays.count] addObject:object];
}];

In Objective-C Categories should come to your mind to create re-uasable code:

@interface NSArray (SplittingInto)
-(NSArray *)arraysBySplittingInto:(NSUInteger)N;
@end

@implementation NSArray (SplittingInto)
-(NSArray *)arraysBySplittingInto:(NSUInteger)N
{
    NSAssert(N > 0, @"N cant be less than 1");
    NSMutableArray *resultArrays = [@[] mutableCopy];
    for (NSUInteger i =0 ; i<N; ++i) {
        [resultArrays addObject:[@[] mutableCopy]];
    }

    [self enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
                                [resultArrays[idx% resultArrays.count] addObject:object];
                            }];
    return resultArrays;
}
@end

Now you can do

NSArray *array = [@[@1,@2,@3,@4,@5,@6,@7,@8,@9,@10,@11,@12] arraysBySplittingInto:2];

array contains

(
        (
        1,
        3,
        5,
        7,
        9,
        11
    ),
        (
        2,
        4,
        6,
        8,
        10,
        12
    )
)



回答3:


Create two NSIndexSets, one for the even indexes and one for the odd, then use objectsAtIndexes: to extract the corresponding slices of the array.




回答4:


Got some time for benchmarking and it turns out that when the input array has more than 10 million, it’s faster to use parallel execution.

Here is the concurrent solution that enumerates the input array twice to prevent race conditions on the output arrays.

static NSArray * concurrent(NSArray *input) {
    NSUInteger capacity = input.count / 2;
    NSArray *split = @[
                       [NSMutableArray arrayWithCapacity:capacity],
                       [NSMutableArray arrayWithCapacity:capacity],
                       ];
    [split enumerateObjectsWithOptions:NSEnumerationConcurrent
                            usingBlock:^(NSMutableArray *output, NSUInteger evenOdd, BOOL *stop) {
                                [input enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
                                    if (index % 2 == evenOdd) {
                                        [output addObject:object];
                                    }
                                }];
                            }];
    return split;
}

I consider this to be the best serial solution, so I used it for benchmarking:

static NSArray * serial(NSArray *input) {
    NSUInteger capacity = input.count / 2;
    NSMutableArray *even = [NSMutableArray arrayWithCapacity:capacity];
    NSMutableArray *odd = [NSMutableArray arrayWithCapacity:capacity];

    [input enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
        NSMutableArray *output = (index % 2) ? odd : even;
        [output addObject:object];
    }];
    return @[ even, odd ];
}

Results

  • 1 million elements
    • Serial: 54.081 ms
    • Concurrent: 65.958 ms (18% worse)
  • 10 million elements
    • Serial: 525.851 ms
    • Concurrent: 412.691 ms (27% better)
  • 100 million elements
    • Serial: 5244.798 ms
    • Concurrent: 4137.939 ms (27% better)

Average of 5 runs.
Input filled with NSNumbers.
Fastest smallest optimization -Os.



来源:https://stackoverflow.com/questions/27208722/objective-c-split-an-array-into-two-separate-arrays-based-on-even-odd-indexes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!