Jika Anda memiliki NSMutableArray
, bagaimana Anda mengocok elemen secara acak?
(Saya punya jawaban sendiri untuk ini, yang diposting di bawah ini, tetapi saya baru mengenal Cocoa dan saya tertarik untuk mengetahui apakah ada cara yang lebih baik.)
Pembaruan: Seperti dicatat oleh @Mukesh, pada iOS 10+ dan macOS 10.12+, ada -[NSMutableArray shuffledArray]
metode yang dapat digunakan untuk mengacak. Lihat https://developer.apple.com/documentation/foundation/nsarray/1640855-shuffledarray?language=objc untuk detailnya. (Tetapi perhatikan bahwa ini menciptakan array baru, daripada mengocok elemen di tempat.)
objective-c
cocoa
shuffle
Kristopher Johnson
sumber
sumber
for (NSUInteger i = self.count; i > 1; i--) [self exchangeObjectAtIndex:i - 1 withObjectAtIndex:arc4random_uniform((u_int32_t)i)];
API
adalah ia mengembalikanArray
yang alamat baru ke lokasi baru di memori.Jawaban:
Anda tidak memerlukan metode swapObjectAtIndex. exchangeObjectAtIndex: withObjectAtIndex: sudah ada.
sumber
Saya memecahkan ini dengan menambahkan kategori ke NSMutableArray.
Sunting: Menghapus metode yang tidak perlu berkat jawaban oleh Ladd.
Sunting: Diubah
(arc4random() % nElements)
menjadiarc4random_uniform(nElements)
berkat oleh jawaban dari Gregory Goltsov dan komentar oleh miho dan blahdiblahSunting: Perbaikan lingkaran, terima kasih atas komentar oleh Ron
Sunting: Ditambahkan, periksa bahwa array tidak kosong, terima kasih atas komentar dari Mahesh Agrawal
sumber
arc4random_uniform(nElements)
sebagai gantiarc4random()%nElements
. Lihat halaman manual arc4random dan penjelasan tentang bias modulo ini untuk informasi lebih lanjut.Karena saya belum bisa berkomentar, saya pikir saya akan berkontribusi dalam tanggapan penuh. Saya memodifikasi implementasi Kristopher Johnson untuk proyek saya dalam beberapa cara (benar-benar berusaha membuatnya sesingkat mungkin), salah satunya adalah
arc4random_uniform()
karena ia menghindari bias modulo .sumber
[self count]
(pengambil properti) dua kali pada setiap iterasi melalui loop. Saya pikir memindahkannya keluar dari loop bernilai kehilangan keringkasan.[object method]
daripadaobject.method
: orang cenderung lupa bahwa nanti tidak semurah mengakses anggota struct, ia datang dengan biaya pemanggilan metode ... sangat buruk dalam satu lingkaran.Jika Anda mengimpor
GameplayKit
, adashuffled
API:https://developer.apple.com/reference/foundation/nsarray/1640855-shuffled
sumber
shuffledArray = [array shuffledArray];
GameplayKit
jadi Anda harus mengimpornya.Solusi yang sedikit lebih baik dan ringkas (dibandingkan dengan jawaban teratas).
Algoritmanya sama dan dijelaskan dalam literatur sebagai " Fisher-Yates shuffle ".
Dalam Objective-C:
Dalam Swift 3.2 dan 4.x:
Di Swift 3.0 dan 3.1:
Catatan: Solusi yang lebih ringkas di Swift dimungkinkan dari penggunaan iOS10
GameplayKit
.Catatan: Algoritma untuk pengocokan tidak stabil (dengan semua posisi dipaksa untuk berubah jika jumlah> 1) juga tersedia
sumber
Ini adalah cara termudah dan tercepat untuk mengocok NSArrays atau NSMutableArrays (puzzle objek adalah NSMutableArray, ini berisi objek puzzle. Saya telah menambahkan indeks variabel objek puzzle yang menunjukkan posisi awal dalam array)
output log:
Anda juga dapat membandingkan obj1 dengan obj2 dan memutuskan apa yang ingin Anda kembalikan nilai yang mungkin adalah:
sumber
Ada perpustakaan populer yang bagus, yang memiliki metode ini sebagai bagiannya, disebut SSToolKit di GitHub . File NSMutableArray + SSToolkitAdditions.h berisi metode acak. Anda juga bisa menggunakannya. Di antara ini, tampaknya ada banyak hal berguna.
Halaman utama perpustakaan ini adalah sini .
Jika Anda menggunakan ini, kode Anda akan seperti ini:
Perpustakaan ini juga memiliki Pod (lihat CocoaPods)
sumber
Dari iOS 10, Anda dapat menggunakan NSArray
shuffled()
dari GameplayKit . Inilah pembantu untuk Array di Swift 3:sumber
Jika elemen memiliki pengulangan.
misalnya array: AAABB atau BBAAA
satu-satunya solusi adalah: ABABA
sequenceSelected
adalah NSMutableArray yang menyimpan elemen obj kelas, yang merupakan petunjuk untuk beberapa urutan.sumber
static
pencegah yang bekerja pada banyak contoh: akan jauh lebih aman dan mudah dibaca untuk menggunakan dua metode, yang utama mengacak dan memanggil metode sekunder, sedangkan metode sekunder hanya memanggil dirinya sendiri dan tidak pernah melakukan perombakan ulang. Juga ada kesalahan pengejaan.sumber
arc4random_uniform([theArray count])
akan lebih baik lagi, jika tersedia pada versi Mac OS X atau iOS yang Anda dukung.Jawaban Kristopher Johnson cukup bagus, tetapi itu tidak sepenuhnya acak.
Diberikan array dari 2 elemen, fungsi ini selalu mengembalikan array terbalik, karena Anda menghasilkan rentang acak Anda selama sisa indeks.
shuffle()
Seperti fungsi yang lebih akuratsumber
i < (count-1)
.)Sunting: Ini tidak benar. Untuk tujuan referensi, saya tidak menghapus posting ini. Lihat komentar tentang alasan mengapa pendekatan ini tidak benar.
Kode sederhana di sini:
sumber