If I have a list of first names, and then a list of second names then how do I print a random selection from 1 of each list
let arrayX = ["James", "Andrew", "Sean"]
let arrayY = ["Smith", "Docherty", "Anderson"]
So I could have James Smith, or Andrew Anderson?
Fetch String with randomly generated index.
let arrayX = ["James", "Andrew", "Sean"]
let arrayY = ["Smith", "Docherty", "Anderson"]
print(arrayX[getRandomIndex(maxRange: arrayX.count)], arrayY[getRandomIndex(maxRange: arrayY.count)])
Function to generate random index:
func getRandomIndex(maxRange: Int) -> Int{
return Int(arc4random_uniform(UInt32(maxRange)))
}
To select a random item from an array you need to generate a random number within it's index range.
You can do this in Swift using arc4random_uniform:
Int(arc4random_uniform(UInt32(arrayX.count)))
Once you know how to do this you can quite easily generate a random name from your arrays:
let arrayX = ["James", "Andrew", "Sean"]
let arrayY = ["Smith", "Docherty", "Anderson"]
let randomForenameIdx = Int(arc4random_uniform(UInt32(arrayX.count)))
let randomSurnameIdx = Int(arc4random_uniform(UInt32(arrayY.count)))
let randomName = "\(arrayX[randomForenameIdx]) \(arrayY[randomSurnameIdx])"
Swift has a very nice way of intertwining arrays using the zip function:
let firstNames = ["James", "Andrew", "Sean"]
let lastNames = ["Smith", "Docherty", "Anderson"]
let randomIndex = Int(arc4random_uniform(UInt32(firstNames.count)))
let randomName = Array(zip(firstNames, lastNames))[randomIndex]
print("\(randomName.0) \(randomName.1)")
zip(_:_:) takes two collections (i. e. arrays) and returns a sequence of tuple pairs, where the elements of each pair are corresponding elements of both collections. The Array initialiser converts the result to an Array of tuples.
This solution always matches first and last names, i. e. you either get James Smith, Andrew Doherty, or Sean Anderson. If this is not what you want then you’ll need two random indexes and no zip function, as suggested in the other answers.
Related
I have an array that is storing a large number of various names in string format. There can be duplicates.
let myArray = ["Jim","Tristan","Robert","Lexi","Michael","Robert","Jim"]
In this case I do NOT know what values will be in the array after grabbing the data from a parse server. So the data imported will be different every time. Just a list of random names.
Assuming I don't know all the strings in the array I need to find the index of the last occurrence of each string in the array.
Example:
If this is my array....
let myArray = ["john","john","blake","robert","john","blake"]
I want the last index of each occurrence so...
blake = 5
john = 4
robert = 3
What is the best way to do this in Swift?
Normally I would just make a variable for each item possibility in the array and then increment through the array and count the items but in this case there are thousands of items in the array and they are of unknown values.
Create an array with elements and their indices:
zip(myArray, myArray.indices)
then reduce into a dictionary where keys are array elements and values are indices:
let result = zip(myArray, myArray.indices).reduce(into: [:]) { dict, tuple in
dict[tuple.0] = tuple.1
}
(myArray.enumerated() returns offsets, not indices, but it would have worked here too instead of zip since Array has an Int zero-based indices)
EDIT: Dictionary(_:uniquingKeysWith:) approach (#Jessy's answer) is a cleaner way to do it
New Dev's answer is the way to go. Except, the standard library already has a solution that does that, so use that instead.
Dictionary(
["john", "john", "blake", "robert", "john", "blake"]
.enumerated()
.map { ($0.element, $0.offset) }
) { $1 }
Or if you've already got a collection elsewhere…
Dictionary(zip(collection, collection.indices)) { $1 }
Just for fun, the one-liner, and likely the shortest, solution (brevity over clarity, or was it the other way around? :P)
myArray.enumerated().reduce(into: [:]) { $0[$1.0] = $1.1 }
I am working with a string array that has about 1100 employee names.
I want to extract the first characters of the employee names so that i can divide the names in table view alphabetically and in different sections. Just like how the contacts app on iPhone does.
i tried this for extraction
var first_char = [String]()
while (i < employeenames.count)//employeenames is the names array
{
first_char.append(String(employeenames[i].prefix(1)))
i+=1
}
This way I am getting the desired characters but the code is taking really long. Also I want to count how many times "A" or "B" shows up in first_char array. Which is again taking another many seconds and smoking the CPU.
Please someone help me with this.
You seem to want to do a "group by" operation on the array of names.
You want to group by the first character, so:
let groups = Dictionary(grouping: employeenames, by: { String($0.first!).uppercased() })
The return value will be [Character: [String]].
To count how many times A shows up, just do:
groups["A"].count
Use this code:
let employeenames = ["Peter", "John", "Frank"]
let firstChars = employeenames.map { String($0.first ?? Character("")) }
The order of the resulting single-character array will be the same as the order of the employeenames array. If you need sorting:
let sortedFirstChars = firstChars.sorted()
Given
let employee: [String] = ["James", "Tom", "Ben", "Jim"]
You can simply write
let firstCharacters = employee.compactMap { $0.first }
Result
print(firstCharacters)
["J", "T", "B", "J"]
Sorting
If you want the initial characters sorted you can add this line
let sortedFirstCharacters = firstCharacters.sorted()
["B", "J", "J", "T"]
Occurrencies
let occurrencies = NSCountedSet(array: firstCharacters)
let occurrenciesOfJ = occurrencies.count(for: Character("J"))
// 2
I need to enumerate a zipped array to check index for each object from array. Below is my code please help me out.
for((index1, index2),(value1, value2)) in zip(array1, array2).enumerated() {
// INDEX OF OBJECT
}
Once you zip the array it is having only one index. Just use it as normal enumerations.
let arr1 = ["1","2","3"]
let arr2 = ["A","B"]
let arr3 = zip(arr1, arr2)
print(arr3)
for (index, (x,y)) in arr3.enumerated() {
print(index, y)
}
enjoy!
You can make use of enumerated to know index of value like this way.
func zipArray() {
let words = ["one", "two", "three", "four"]
let numbers = 1...4
let zipArray = Array(zip(words, numbers))
print(zipArray)
for (index, tuple) in zipArray.enumerated() {
print("Index : \(index): Word :\(tuple.0) Number : \(tuple.1)")
}
}
Once zip perform on two array then it returns another array with pair of inputs.
So you can perform enumerated operation on zipped array using above code and get index and value as tuple. Then for individual element of tuple index would be same.
There may be better way. But this will fulfill your purpose of index.
I am currently trying to make an app for iOS but I can't get some simple code down. Basically I need to randomly select 5 elements from an array list without repeating an element. I have a rough draft, but it only displays one element.
Here is my code:
let array1 = ["salmon", "turkey", "salad", "curry", "sushi", "pizza"]
let randomIndex1 = Int(arc4random_uniform(UInt32(array1.count)))
print(array1[randomIndex1])
You can do it like this:
let array1 = ["salmon", "turkey", "salad", "curry", "sushi", "pizza", "curry", "sushi", "pizza"]
var resultSet = Set<String>()
while resultSet.count < 5 {
let randomIndex = Int(arc4random_uniform(UInt32(array1.count)))
resultSet.insert(array1[randomIndex])
}
let resultArray = Array(resultSet)
print(resultArray)
A set can contain unique elements only, so it can't have the same element more than once.
I created an empty set, then as long as the array contains less than 5 elements (the number you chose), I iterated and added a random element to the set.
In the last step, we need to convert the set to an array to get the array that you want.
SWIFT 5.1
This has been answered, but I dare to come with a more simple solution.
If you take your array and convert it into a Set you will remove any duplicated items and end up with a set of unique items in no particular order since the nature of a Set is unordered.
https://developer.apple.com/documentation/swift/set
If you then convert it back to an array and pick 5 elements you will end up with an array of random items.
But it's just 1 line ;)
Example:
var original = ["A","B","C","C","C","D","E","F","G","H"]
let random = Array(Set(original)).prefix(5)
Example print:
["B", "G", "H", "E", "C"]
The only requirement is your objects must conform to the Hashable protocol. Most standard Swift types do, otherwise, it's often simple to make your own types conform.
https://developer.apple.com/documentation/swift/hashable
If you don't care about changing the original array, the following code will put the picked elements at the end of the array and then it will return the last part of the array as a slice.
This is useful if you don't care about changing the original array, the advantage is that it doesn't use extra memory, and you can call it several times on the same array.
extension Array {
mutating func takeRandomly(numberOfElements n: Int) -> ArraySlice<Element> {
assert(n <= self.count)
for i in stride(from: self.count - 1, to: self.count - n - 1, by: -1) {
let randomIndex = Int(arc4random_uniform(UInt32(i + 1)))
self.swapAt(i, randomIndex)
}
return self.suffix(n)
}
}
Example:
var array = [1,2,3,4]
let a1 = array.takeRandomly(numberOfElements: 2)
let a2 = array.takeRandomly(numberOfElements: 2)
swift-algorithms now includes an extension to Sequence called randomSample.
import Algorithm
var array1 = ["salmon", "turkey", "salad", "curry", "sushi", "pizza"]
array1.randomSample(count: 5)
Just my ¢2:
Moe Abdul-Hameed's solution has one theoretical drawback: if you roll the same randomIndex in every iteration, the while loop will never exit. It's very unlike tho.
Another approach is to create mutable copy of original array and then exclude picked items:
var source = array1
var dest = [String]()
for _ in 1...5 {
let randomIndex = Int(arc4random_uniform(UInt32(source.count)))
dest.append(source[randomIndex])
source.remove(at: randomIndex)
}
print(dest)
var array1 = ["salmon", "turkey", "salad", "curry", "sushi", "pizza"]
while array1.count > 0 {
// random key from array
let arrayKey = Int(arc4random_uniform(UInt32(array1.count)))
// your random number
let randNum = array1[arrayKey]
// make sure the number ins't repeated
array1.removeAtIndex(arrayKey)
}
By removing your picked value from array, prevent's from duplicates to be picked
As title says (not sure about my english). I am new to swift language.
I am currently working in a swift app where a a user pick the correct answer in a randomize questions.
I am using gameplaykit for randomizing
var questions = ["question1", "question2", "question3", "question4", "question5"]// my question array
func askQuestion(){
countries = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: countries) as! [String]//to randomize
...
}
So my app are working fine in randomizing all the question1...questionN repeateadly but what i want is to have a limit i.e. only 5 questions will be given.
I searched but found "getting the specific index of an array", not what i'm looking for.
Could you help me how to achieve this? or Is my approach right?
Thanks
You can use prefix(n) on an array to get the first n elements, such as:
countries = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: countries).prefix(3) as! [String]
You can get first N numbers of elements using Prefix. Here is an example
let n = 5 // could be any number of your choice
let firstNNumbers = questions.prefix(n)
Try this -
func askQuestion() {
countries = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: countries) as! [String]
//After randomize your array use prefix method -
let limit = 5
let updatedCountries = Array(countries.prefix(limit)) // Use this `updatedCountries` array to display in UI.
}