I've array with several elements, I want to generate a random element from that array and after generating I want to remove that element. I tried remove method but it returns an error Cannot find 'randSachmeli' in scope randSachmeli is a random generated array
struct SachmelebiData {
let name:String
let link:String
}
var mainMenu:[SachmelebiData] = [
SachmelebiData(name: "ხინკალი", link: ""),
SachmelebiData(name: "მწვადი", link: ""),
SachmelebiData(name: "yleyveri", link: "")
]
let yvelaSachmeli:[SachmelebiData] = mainMenu
var randSachemli = yvelaSachmeli.randomElement()
yvelaSachmeli.remove(randSachmeli)
Get random elements from the index by getting random index from array indices. And then delete the element by index.
var yvelaSachmeli:[SachmelebiData] = mainMenu
// Get the random element from the array
guard let randomIndexFromArray = yvelaSachmeli.indices.randomElement() else {
return
}
// Get the element from the index
var randSachemli = yvelaSachmeli[randomIndexFromArray]
// Remove the element by index
yvelaSachmeli.remove(at: randomIndexFromArray)
Related
I am trying to filter my dictionary according to user input in UISearchController. I have following model and array of objects.
struct People {
var name: String
var id: Int
}
let first = People(name: "Atalay", id: 1)
let second = People(name: "Ahmet", id: 2)
let third = People(name: "Mehmet", id: 3)
let fourth = People(name: "Yusuf", id: 4)
let peoples: [People] = [first, second, third, fourth, fifth]
I put them into a dictionary to create section indexed table view with following code.
var dict: [String: [People]] = Dictionary(grouping: peoples, by: { (people) -> String in
return String(people.name.prefix(1))
})
Above code gives me a dictionary with first letter of People names. Now, I would like to filter my array according to user input. However, I tried following code for filtering but it is not working as I expected.
let filteredDict = (dict.filter { $0.1.contains { $0.name.lowercased().contains("ata") } })
It returns all "A" letter section indexes like ["A": People(name: "Atalay", id: 1), People(name: "Ahmet", id: 2)]
How can I achieve filter also my array inside dictionary?
If I'm not mistaken, you want your final dictionary to have all the keys and only the filtered array of items as the values. If that is right, reduce is the tool for that:
let filtered = dict.reduce(into: [String: [People]]()) {
$0[$1.key] = $1.value.filter { $0.name.lowercased().contains("ata") }
}
I decided it was simplest to get this right by using an old fashioned for loop and filter each group separately
var filtered = [String: [People]]()
for (k, v) in dict {
let result = v.filter {$0.name.lowercased().contains("ata")}
if result.count > 0 {
filtered[k] = result
}
}
Note that if you want to keep all the groups in the result dictionary just skip the if result.count > 0 condition
How can I achieve filter also my array inside dictionary?
You should have an array first, you can use flatMap to group all the values in your filteredDict
let array = filteredDict.flatMap { $0.value }
Then you just filter the array as usually
let filteredArray = array.filter { $0.name.lowercased().contains("ata") }
I have an array myarray and I am using a for loop to get a few information which I add to myarray. But next time the for-loop runs, I don't want to create a separate index, but instead the 2nd time and so on, I want to append the information to myarray[0].
How do I do that?
var myarray = [String]()
for var j in 0 < 12 {
// do some stuff
for var i in 0 ..< 10 {
let parta = json?["users"][j]["name"].string
let partb = json?["users"][j]["Lname"].string
let partc = json?["users"][j]["dob"].string
myarray.append("\(parta)-\(partb)-\(partc)---")
// Here when the for loop comes back again (i = 1) , i dont want to make
// myarray[1] , but instead i want myarray[0] ,
// having value like [parta-partb-partc--parta-partb-partc]
}
}
Basically what I am trying to do is, append the new name/lname/dob values at myarray[0] without affecting the current value/string at myarray[0].
You can insert single element and also add array as below.
Swift 5
var myarray = [String]()
myarray.insert("NewElement", at: 0)
myarray.insert(contentsOf: ["First", "Second", "Third"], at: 0)
If I understand your question correctly, you want to create one long string and add the new data always at the beginning of the string. One way to do that would be:
// Store somewhere
var myString = String()
for var i in(0..<10) {
let parta = json?["name"].string
let partb = json?["Lname"].string
let partc = json?["dob"].string
let newString = "\(parta)-\(partb)-\(partc)---")
newString.append(myString)
myString = newString
// Here when the for loop comes back again (i = 1) , i dont want to make
//myarray[1] , but instead i want myarray[0] ,
//having value like [parta-partb-partc--parta-partb-partc]
}
I have an array of Super Hero objects. I want to group the superheroes based on the name property into separated arrays and then count how many objects are in each individual separated array
Object:
class SuperHero{
var name: String?
var power: Bool?
}
Array of superheroes (there can be an infinite num of superheroes)
var superHeroes = [SuperHero]()
let superHero1 = SuperHero()
superHero1.name = "SuperMan"
superHero1.power = true
superHeroes.append(superHero1)
let superHero2 = SuperHero()
superHero2.name = "BatMan"
superHero2.power = true
superHeroes.append(superHero2)
let superHero3 = SuperHero()
superHero3.name = "BatMan"
superHero3.power = true
superHeroes.append(superHero3)
let superHero4 = SuperHero()
superHero4.name = "SuperMan"
superHero4.power = true
superHeroes.append(superHero4)
//etc...
Use name property to sort:
let sortedHeros = superHeroes.sort{$0.name < $1.name}
for hero in sortedHeros{
print(hero.name)
/*
prints
BatMan
BatMan
SuperMan
SuperMan
*/
}
How do I put the sorted array into separate arrays then print the count of each separated array?
//this is what I want
separatedArraysOfSuperHeroes = [[superHero2, superHero3], [superHero1, superHero4]]
//subscriprting isn't ideal because i'll never know the exact number of separated arrays
print(separatedArraysOfSuperHeroes[0].count)
print(separatedArraysOfSuperHeroes[1].count)
As per the comments the reason why I want sub arrays is because I want to use them to populate different tableview sections. For i.e. inside my tableview I would now have a 2 sections. The first section would have a header that says "Batman" with 2 Batman objects inside of it and the second section would have a header that says Superman with 2 Superman objects inside of it. The count property would show the number of super hero objects inside each section.
func getSeparatedArrayBasedOnName(superHeroes: [SuperHero]) -> [[SuperHero]] {
guard let superNames = NSOrderedSet.init(array: superHeroes.map { $0.name ?? "" }).array as? [String] else {
print("Something went wrong with conversion")
return [[SuperHero]]()
}
var filteredArray = [[SuperHero]]()
for superName in superNames {
let innerArray = superHeroes.filter({ return $0.name == superName })
filteredArray.append(innerArray)
}
for array in filteredArray {
for hero in array {
print(hero.name ?? "")
}
}
return filteredArray
}
I have 2 arrays of [NSURL] and they have the same elements with different order. I am trying to use the array1's indexpath to get the member, and detect member's indexPath in the other array.
I couldn't figure out if I can detect the member's index on type NSURL. I thought one way could be using for loop for the second array, however the way I could think of was..
For loop through the array2 and convert each to string to have a [string] and using another for loop to find the index of the string that I'm looking for
let array1 = [NSURL]()
let array2 = [NSURL]()
array1 = [abc, qwe, jkl]
array2 = [jkl, abc, qwe]
// To wrap up..
// For jkl, I want to use array1[2] and get array2[?]
let searchIndex = 2
if array1[2].absoluteString.isNotEmpty {
let stringToSearch = array1[2].absoluteString
}
let index = array2.indexOf { $0.absoluteString == array1[2].absoluteString }
is there a possibility to get an object from an array with an specific property? Or do i need to loop trough all objects in my array and check if an property is the specific i was looking for?
edit: Thanks for given me into the correct direction, but i have a problem to convert this.
// edit again: A ok, and if there is only one specific result? Is this also a possible method do to that?
let imageUUID = sender.imageUUID
let questionImageObjects = self.formImages[currentSelectedQuestion.qIndex] as [Images]!
// this is working
//var imageObject:Images!
/*
for (index, image) in enumerate(questionImageObjects) {
if(image.imageUUID == imageUUID) {
imageObject = image
}
}
*/
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
var imageObject = questionImageObjects.filter( { return $0.imageUUID == imageUUID } )
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
You have no way to prove at compile-time that there is only one possible result on an array. What you're actually asking for is the first matching result. The easiest (though not the fastest) is to just take the first element of the result of filter:
let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first
imageObject will now be an optional of course, since it's possible that nothing matches.
If searching the whole array is time consuming, of course you can easily create a firstMatching function that will return the (optional) first element matching the closure, but for short arrays this is fine and simple.
As charles notes, in Swift 3 this is built in:
questionImageObjects.first(where: { $0.imageUUID == imageUUID })
Edit 2016-05-05: Swift 3 will include first(where:).
In Swift 2, you can use indexOf to find the index of the first array element that matches a predicate.
let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})
This is bit faster compared to filter since it will stop after the first match. (Alternatively, you could use a lazy sequence.)
However, it's a bit annoying that you can only get the index and not the object itself. I use the following extension for convenience:
extension CollectionType {
func find(#noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
return try indexOf(predicate).map({self[$0]})
}
}
Then the following works:
questionImageObjects.find({$0.imageUUID == imageUUID})
Yes, you can use the filter method which takes a closure where you can set your logical expression.
Example:
struct User {
var firstName: String?
var lastName: String?
}
let users = [User(firstName: "John", lastName: "Doe"), User(firstName: "Bill", lastName: "Clinton"), User(firstName: "John", lastName: "Travolta")];
let johns = users.filter( { return $0.firstName == "John" } )
Note that filter returns an array containing all items satisfying the logical expression.
More info in the Library Reference
Here is a working example in Swift 5
class Point{
var x:Int
var y:Int
init(x:Int, y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x:1, y:2)
var p2 = Point(x:2, y:3)
var p3 = Point(x:1, y:4)
var points = [p1, p2, p3]
// Find the first object with given property
// In this case, firstMatchingPoint becomes p1
let firstMatchingPoint = points.first{$0.x == 1}
// Find all objects with given property
// In this case, allMatchingPoints becomes [p1, p3]
let allMatchingPoints = points.filter{$0.x == 1}
Reference:
Trailing Closure
Here is other way to fetch particular object by using object property to search an object in array.
if arrayTicketsListing.contains({ $0.status_id == "2" }) {
let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!]
print(ticketStatusObj.status_name)
}
Whereas, my arrayTicketsListing is [TicketsStatusList] contains objects of TicketsStatusList class.
// TicketsStatusList class
class TicketsStatusList {
internal var status_id: String
internal var status_name: String
init(){
status_id = ""
status_name = ""
}
}