有些情況下需要打亂一個(gè)數(shù)組的順序,比如牌類(lèi)游戲的洗牌。
如果是 Java 服務(wù)器,Java SDK 提供了一個(gè) randomArray 的 API。但 iOS 并沒(méi)有提供,Let's DIY。
主要思想是利用 iOS 提供的排序函數(shù) sortUsingComparator: ,正常情況下的比較會(huì)返回 NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending,對(duì)應(yīng)的整形值分別是 -1, 0, 1,如果我們隨機(jī)返回這三個(gè)數(shù)呢?
NSMutableArray *array = [@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"] mutableCopy];
[array sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return (NSInteger)arc4random() % 3 - 1;
}];
這么做會(huì)不會(huì)有什么風(fēng)險(xiǎn)呢?比如在排序過(guò)程中,進(jìn)行了校驗(yàn),如果進(jìn)行了校驗(yàn),肯定是通不過(guò),有可能導(dǎo)致死循環(huán)。
所以我們加上兩個(gè)輸出,來(lái)驗(yàn)證一下結(jié)果,并順便一探 iOS SDK 為我們提供的排序算法是哪一類(lèi)。
NSMutableArray *array = [@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8"] mutableCopy];
NSLog(@"%@, %p", array, array);
[array sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
NSInteger randomResult = (NSInteger)arc4random() % 3 - 1;
NSLog(@"%@, %@, %@", obj1, obj2, @(randomResult));
return randomResult;
}];
NSLog(@"%@, %p", array, array);
為了方便查看,我將 NSLog 輸出的前一段信息去掉了,輸出結(jié)果為:
1, 2
3, 4
2, 3
2, 4
5, 6
7, 8
7, 9
5, 8
6, 8
6, 7
3, 5
3, 8
4, 8
4, 6
4, 7
2, 7
2, 9
1, 9
(
5,
3,
8,
6,
4,
7,
2,
9,
1
)
第二次運(yùn)行結(jié)果為:
1, 2
3, 4
2, 4
1, 4
1, 3
5, 6
7, 8
8, 9
7, 9
6, 7
6, 9
6, 8
5, 8
2, 7
2, 9
2, 6
2, 8
4, 8
4, 5
(
7,
9,
6,
2,
8,
5,
4,
1,
3
)
可以看出是隨機(jī)排了序,并沒(méi)有引起死循環(huán)或者其他問(wèn)題。
那么使用的排序方式是哪一種呢?
盡管最后結(jié)尾的比較順序不盡相同,但從前面幾次還說(shuō)可以看出一些端倪,首先是前4個(gè)進(jìn)行比較,然后說(shuō)后5個(gè)進(jìn)行比較,所以應(yīng)該是二分排序?
然而并不是,如果我們?cè)谂判蜻^(guò)程中,輸出這個(gè)數(shù)組,你會(huì)發(fā)現(xiàn)這個(gè)數(shù)組在排序過(guò)程中并沒(méi)有發(fā)生變化。
或者找一個(gè)簡(jiǎn)單的無(wú)序數(shù)組,然后按正常的方式輸出 obj1 obj2 以及正確的比較結(jié)果,然后手動(dòng)跟著一步一步的排序,你會(huì)發(fā)現(xiàn),按照這些根本沒(méi)用辦法正確排序。
所以我推測(cè),在排序時(shí),有另外的一個(gè)數(shù)據(jù)區(qū),這個(gè)排序先通過(guò)比較取得相關(guān)的信息,并將信息存入這個(gè)數(shù)據(jù)區(qū),最后根據(jù)信息來(lái)調(diào)整順序。
如果你知道,歡迎在評(píng)論區(qū)回復(fù)。
Github
我封裝了 OC 版本和 Swift 版本的隨機(jī)數(shù)組分類(lèi)
如果你有更好的建議,歡迎在評(píng)論區(qū)回復(fù)。