-4

I have an NSMutableArray containing ten custom objects in a particular order.

What I need is to rearrange the objects so that the second half of the array is interleaved with the first half:

Before: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
After: 1, 6, 2, 7, 3, 8, 4, 9, 5, 10

How can I accomplish this?

jscs
  • 63,694
  • 13
  • 151
  • 195
moujib
  • 742
  • 2
  • 7
  • 26
  • Why not do it simple like:NSArray *arr = @[Object 1, Object 2, Object 3, Object 4, Object 5, Object 6, Object 7, Object 8, Object 9, Object 10]; => NSArray *results = @[arr[0], arr[5], arr[1], arr[6], arr[2], arr[7], arr[3], arr[8], arr[4], arr[9]]; – larva Dec 07 '14 at 14:53

3 Answers3

1
  • (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2

  • (void)sortUsingComparator:(NSComparator)cmptr

zaph
  • 111,848
  • 21
  • 189
  • 228
1

What you are looking for is called a shuffle (think shuffling a deck of cards - same data, different order). The following method can be used to swap two objects within a mutable array.

- (void)exchangeObjectAtIndex:(NSUInteger)idx1
        withObjectAtIndex:(NSUInteger)idx2

You cannot enumerate over an array while you are modifying it, and I would refrain from looping over the elements of the array as well. Instead, create a for-loop with an index and use arc4random to generate the second swap index.

for (NSUInteger n = 0; n < array.count; n++) {
    NSUInteger m = arc4random_uniform(array.count);
    [array exchangeObjectAtIndex:n withObjectAtIndex:m];
}

There's more sophistication that can be added like checking to see if n == m or negating some kind of bias but this should get you a "mostly" random sampling of the original array.


[Swift]

Swift exchange Method swaps two items in a mutable array. func exchangeObjectAtIndex(_ idx1: Int, withObjectAtIndex idx2: Int)

User Nate Cook provides several good shuffling methods for Swift here. I'm copying his mutating Array method here, as it is closest to the Objective-C method described above.

extension Array {
    mutating func shuffle() {
        for i in 0..<(count - 1) {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            exchangeObjectAtIndex(i, withObjectAtIndex: j)
        }
    }
}
var numbers = [1, 2, 3, 4, 5, 6, 7, 8]
numbers.shuffle() 
Community
  • 1
  • 1
Stephen Furlani
  • 6,794
  • 4
  • 31
  • 60
0

Why not create a second NSArray, in which you put your values in the order you want to? After that, if you wish to use the first array, you remove all items from it

[firstArray removeAllObjects];

then put the items back from the second array:

for (int i = 0; i < [secondArray count]; i++)
{
[firstArray addObject: [secondArray objectAtIndex:i]];
}
Gergely Kovacs
  • 1,045
  • 2
  • 10
  • 28