2

I have a VC with a tableView inside where i fill manually an array by multiple selecting of items from my tableView's rows. In this VC i have an array

var list : [QCategoryy] = [QCategoryy]()
list = NearbyPlaces.getCategories()

where getCategories() is

static func getCategories() -> [QCategoryy] {
        let list:[QCategoryy] = [QCategoryy(name: "bar", image: UIImage(named: "bar_button.png")!), QCategoryy(name :"night_club", image: UIImage(named: "nightclub_button.png")!), QCategoryy(name: "movie_theater", image: UIImage(named: "cinema_button.png")!), QCategoryy(name: "restaurant", image: UIImage(named: "restaurant_button.png")!), QCategoryy(name: "gym", image: UIImage(named: "gym_button.png")!), QCategoryy(name: "spa", image: UIImage(named: "spa_button.png")!), QCategoryy(name: "museum", image: UIImage(named: "museum_button.png")!)]
        return list
    }

these items (bar, gym, spa etc.) will fill my tableView cells and when i select them i'll create my array selectedCategories how you can see here:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == nearbySearchSegueIdentifier {
            let selectedCategories: [QCategoryy] = tableView.indexPathsForSelectedRows?.map({ (indexPath) -> QCategoryy in
                return list[indexPath.row] }) ?? []

            if let selectedRows = tableView.indexPathsForSelectedRows {

                if let vc : nextClass = segue.destination as? nextClass {


                vc.categories = selectedCategories


            }
        }
    }
}

now i would like to know how can i fill this array (selectedCategories) without selecting the cells of the tableView but in random way by pressing a button, so i want to fill the array with random items of my var list : [QCategoryy] = [QCategoryy]() with a button tap, how can i do?

UPDATE

struct QCategoryy {
    var name: String
    var image: UIImage
    var isSelected = false

    init(name:String, image:UIImage) {
        self.name = name
        self.image = image

    }
}

extension QCategoryy: ExpressibleByStringLiteral {


    init(stringLiteral value: String) {
        self.name = value
        self.image = UIImage()

    }
    init(unicodeScalarLiteral value: String) {
        self.init(name: value, image: UIImage())
    }
    init(extendedGraphemeClusterLiteral value: String) {
        self.init(name: value, image: UIImage())
    }
}
2
  • Does it matter if you get duplicates? Commented Nov 15, 2017 at 13:48
  • is better if i do not get duplicate Commented Nov 15, 2017 at 13:50

1 Answer 1

1

The route you likely want to go is to "shuffle" the array of categories, and then take the first n number of elements from the array.

Say you have an array of numbers 1 through 10:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

and you want to get 6 random elements. If you simply did a Get Random Element type of call 6 times, you would very likely end up with duplicates.

So, if you perform a Shuffle on the array, your new array may look like this:

[7, 2, 9, 5, 3, 4, 1, 10, 8, 6]

and you can get the first 6 elements - which will be random without duplicates.

The elements can be anything... I'm just showing numbers here for explanation.


Edit

For example... add this code to your project:

extension MutableCollection where Indices.Iterator.Element == Index {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            guard d != 0 else { continue }
            let i = index(firstUnshuffled, offsetBy: d)
            swap(&self[firstUnshuffled], &self[i])
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Iterator.Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

Then, in prepare for segue, you could do:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == nearbySearchSegueIdentifier {
            if let vc : nextClass = segue.destination as? nextClass {

                // use ALL QCategoryy objects, in random order
                vc.categories = NearbyPlaces.getCategories().shuffled()

                // or, use 4 random QCategoryy objects
                //vc.categories = NearbyPlaces.getCategories().shuffled()[0...3]

            }
        }
    }
}

This shuffle extension, and others, can be found here: https://stackoverflow.com/a/24029847/6257435

Sign up to request clarification or add additional context in comments.

4 Comments

ok understand, and this is your example [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] with an array of numbers, to write instead an array with the elements of categories?
Yes - if you look at the shuffle code in the link, you will see that it shuffles whatever the objects are in the array - it doesn't matter whether it's an array of numbers, buttons, views, custom objects, etc.
ok so in my case i have to copy and paste that code using with my list?
ah ok i have to modify the prepare in the end, now it's all clear, thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.