洗牌 NSMutableArray 的最佳方法是什么?
如果你有一个 NSMutableArray
,你如何随机地打乱元素?
(我对此有自己的答案,发布在下面,但我是 Cocoa 的新手,我有兴趣知道是否有更好的方法。)
更新:正如 @Mukesh 所指出的,从 iOS 10+ 开始, macOS 10.12+,有一个 -[NSMutableArray shuffledArray]
方法可用于随机播放。 请参阅 https://developer.apple.com/documentation/foundation/ nsarray/1640855-shuffledarray?language=objc 了解详细信息。 (但请注意,这会创建一个新数组,而不是将元素打乱到位。)
If you have an NSMutableArray
, how do you shuffle the elements randomly?
(I have my own answer for this, which is posted below, but I'm new to Cocoa and I'm interested to know if there is a better way.)
Update: As noted by @Mukesh, as of iOS 10+ and macOS 10.12+, there is an -[NSMutableArray shuffledArray]
method that can be used to shuffle. See https://developer.apple.com/documentation/foundation/nsarray/1640855-shuffledarray?language=objc for details. (But note that this creates a new array, rather than shuffling the elements in place.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
如果导入 GameplayKit,则会有一个 shuffled API:
https://developer.apple.com/reference/foundation/nsarray/1640855-shuffled
If you import
GameplayKit
, there is ashuffled
API:https://developer.apple.com/reference/foundation/nsarray/1640855-shuffled
从 iOS 10 开始,您可以使用 NSArray
shuffled()
来自 GameplayKit。 这是 Swift 3 中数组的帮助器:From iOS 10, you can use NSArray
shuffled()
from GameplayKit. Here is an helper for Array in Swift 3:有一个不错的流行库,它包含此方法,名为 GitHub 中的 SSToolKit。
文件 NSMutableArray+SSToolkitAdditions.h 包含 shuffle 方法。 您也可以使用它。 这其中,似乎有很多有用的东西。
该库的主页位于此处。
如果你使用这个,你的代码将是这样的:
这个库也有一个Pod(参见CocoaPods)
There is a nice popular library, that has this method as it's part, called SSToolKit in GitHub.
File NSMutableArray+SSToolkitAdditions.h contains shuffle method. You can use it also. Among this, there seem to be tons of useful things.
The main page of this library is here.
If you use this, your code will be like this:
This library also has a Pod (see CocoaPods)
如果元素有重复。
例如数组:AAABB 或 BBAAA
唯一的解决方案是: ABABA
sequenceSelected
是一个 NSMutableArray,它存储类 obj 的元素,这些元素是指向某个序列的指针。If elements have repeats.
e.g. array: A A A B B or B B A A A
only solution is: A B A B A
sequenceSelected
is an NSMutableArray which stores elements of class obj, which are pointers to some sequence.Kristopher Johnson 的答案非常好,但事实并非如此完全随机。
给定一个包含 2 个元素的数组,此函数始终返回倒排数组,因为您正在生成其余索引上的随机范围。 更准确的
shuffle()
函数如下Kristopher Johnson's answer is pretty nice, but it's not totally random.
Given an array of 2 elements, this function returns always the inversed array, because you are generating the range of your random over the rest of the indexes. A more accurate
shuffle()
function would be like编辑:这是不正确的。出于参考目的,我没有删除这篇文章。 请参阅有关此方法不正确原因的评论。
简单的代码在这里:
Edit: This is not correct. For reference purposes, I did not delete this post. See comments on the reason why this approach is not correct.
Simple code here:
一个稍微改进且简洁的解决方案(与最佳答案相比)。
该算法是相同的,在文献中描述为“Fisher-Yates shuffle”。
在 Objective-C 中:
在 Swift 3.2 和 4.x 中:
在 Swift 3.0 和 3.1 中:
注意: 可以从 Swift 中获得更简洁的解决方案iOS10 使用
GameplayKit
。注意:一种不稳定洗牌算法(如果出现以下情况,所有位置都被迫改变)计数 > 1) 也可用
A slightly improved and concise solution (compared to the top answers).
The algorithm is the same and is described in literature as "Fisher-Yates shuffle".
In Objective-C:
In Swift 3.2 and 4.x:
In Swift 3.0 and 3.1:
Note: A more concise solution in Swift is possible from iOS10 using
GameplayKit
.Note: An algorithm for unstable shuffling (with all positions forced to change if count > 1) is also available
这是最简单、最快的洗牌 NSArray 或 NSMutableArray 的方法
(对象拼图是一个 NSMutableArray,它包含拼图对象。我已添加到
拼图对象变量索引,指示数组中的初始位置)
日志输出:
您也可以将 obj1 与 obj2 进行比较并决定要返回什么
可能的值为:
This is the simplest and fastest way to shuffle NSArrays or NSMutableArrays
(object puzzles is a NSMutableArray, it contains puzzle objects. I've added to
puzzle object variable index which indicates initial position in array)
log output:
you may as well compare obj1 with obj2 and decide what you want to return
possible values are:
由于我还不能发表评论,我想我应该做出完整的回应。 我以多种方式修改了 Kristopher Johnson 项目的实现(确实试图使其尽可能简洁),其中之一是
arc4random_uniform()
因为它避免了 模偏差。Since I can't yet comment, I thought I'd contribute a full response. I modified Kristopher Johnson's implementation for my project in a number of ways (really trying to make it as concise as possible), one of them being
arc4random_uniform()
because it avoids modulo bias.我通过向 NSMutableArray 添加一个类别解决了这个问题。
编辑:由于 Ladd 的回答,删除了不必要的方法。
编辑:将
(arc4random() % nElements)
更改为arc4random_uniform(nElements)
,感谢Gregory Goltsov的回答以及miho和blahdiblah的评论编辑: 循环改进,感谢 Ron 的评论
编辑: 添加了检查数组不为空的功能,感谢 Mahesh Agrawal 的评论
I solved this by adding a category to NSMutableArray.
Edit: Removed unnecessary method thanks to answer by Ladd.
Edit: Changed
(arc4random() % nElements)
toarc4random_uniform(nElements)
thanks to answer by Gregory Goltsov and comments by miho and blahdiblahEdit: Loop improvement, thanks to comment by Ron
Edit: Added check that array is not empty, thanks to comment by Mahesh Agrawal
您不需要 swapObjectAtIndex 方法。 exchangeObjectAtIndex:withObjectAtIndex: 已存在。
You don't need the swapObjectAtIndex method. exchangeObjectAtIndex:withObjectAtIndex: already exists.