Если у вас есть NSMutableArray
, как вы перемешиваете элементы случайным образом?
(У меня есть собственный ответ на этот вопрос, который опубликован ниже, но я новичок в Какао, и мне интересно знать, есть ли лучший способ.)
Обновление: как отмечает @Mukesh, начиная с iOS 10+ и macOS 10.12+, существует -[NSMutableArray shuffledArray]
метод, который можно использовать для перемешивания. Подробнее см. Https://developer.apple.com/documentation/foundation/nsarray/1640855-shuffledarray?language=objc . (Но учтите, что это создает новый массив, а не перетасовывает элементы на месте.)
objective-c
cocoa
shuffle
Кристофер Джонсон
источник
источник
for (NSUInteger i = self.count; i > 1; i--) [self exchangeObjectAtIndex:i - 1 withObjectAtIndex:arc4random_uniform((u_int32_t)i)];
API
том, что он возвращает новое,Array
которое обращается к новому месту в памяти.Ответы:
Вам не нужен метод swapObjectAtIndex. exchangeObjectAtIndex: withObjectAtIndex: уже существует.
источник
Я решил это, добавив категорию в NSMutableArray.
Изменить: Удален ненужный метод благодаря ответу Лэдд.
Изменить: изменено
(arc4random() % nElements)
наarc4random_uniform(nElements)
благодаря ответу Грегори Гольцов и комментарии по Михо и blahdiblahИзменить: улучшение петли, благодаря комментарию Рона
Редактировать: добавлена проверка, что массив не пуст, благодаря комментарию Махеш Агравал
источник
arc4random_uniform(nElements)
вместоarc4random()%nElements
. См. Man-страницу arc4random и это объяснение смещения по модулю для получения дополнительной информации.Поскольку я пока не могу комментировать, я подумала, что внесу полный ответ. Я изменил реализацию Кристофера Джонсона для своего проекта несколькими способами (действительно пытаясь сделать его как можно более кратким), одним из них является то,
arc4random_uniform()
что он избегает смещения по модулю .источник
[self count]
(getter) дважды на каждой итерации цикла. Я думаю, что удаление этого из цикла стоит потери краткости.[object method]
вместоobject.method
: люди склонны забывать, что последнее не так дешево, как доступ к члену структуры, оно идет со стоимостью вызова метода ... очень плохо в цикле.Если вы импортируете
GameplayKit
, естьshuffled
API:https://developer.apple.com/reference/foundation/nsarray/1640855-shuffled
источник
shuffledArray = [array shuffledArray];
GameplayKit
поэтому вы должны импортировать его.Немного улучшенное и краткое решение (по сравнению с основными ответами).
Алгоритм такой же и описан в литературе как « случайный случай Фишера-Йейтса». ».
В Objective-C:
В Swift 3.2 и 4.x:
В Swift 3.0 и 3.1:
Примечание: более краткое решение в Swift возможно с использованием iOS10
GameplayKit
.Примечание: также доступен алгоритм нестабильной тасовки (все позиции вынуждены менять, если число> 1).
источник
Это самый простой и быстрый способ перемешать NSArrays или NSMutableArrays (объектные головоломки - это NSMutableArray, он содержит объекты головоломки. Я добавил в индекс переменной объекта головоломки, который указывает начальную позицию в массиве)
вывод журнала:
Вы также можете сравнить obj1 с obj2 и решить, что вы хотите вернуть возможные значения:
источник
Есть хорошая популярная библиотека, в которой есть этот метод, который называется SSToolKit в GitHub. . Файл NSMutableArray + SSToolkitAdditions.h содержит метод shuffle. Вы можете использовать это также. Среди этого, кажется, есть тонны полезных вещей.
Главная страница этой библиотеки находится здесь .
Если вы используете это, ваш код будет выглядеть так:
Эта библиотека также имеет Pod (см. CocoaPods)
источник
С iOS 10 вы можете использовать NSArray
shuffled()
из GameplayKit . Вот помощник для Array в Swift 3:источник
Если элементы повторяются.
например, массив: AAABB или BBAAA
Единственное решение: ABABA
sequenceSelected
NSMutableArray, который хранит элементы класса obj, которые являются указателями на некоторую последовательность.источник
static
предотвращает» работу с несколькими экземплярами: было бы намного безопаснее и удобочитаемее использовать два метода, основной из которых выполняет перемешивание и вызывает вторичный метод, тогда как вторичный метод вызывает только сам себя и никогда не переставляет. Также есть орфографическая ошибка.источник
arc4random_uniform([theArray count])
было бы еще лучше, если бы оно было доступно в поддерживаемой вами версии Mac OS X или iOS.Ответ Кристофера Джонсона довольно приятный, но не совсем случайный.
Учитывая массив из 2 элементов, эта функция всегда возвращает инвертированный массив, потому что вы генерируете диапазон случайных чисел по остальным индексам. Более точная
shuffle()
функция будет какисточник
i < (count-1)
.)Редактировать: это не правильно. Для справки я не удалил этот пост. Смотрите комментарии о причине, почему этот подход не является правильным.
Простой код здесь:
источник