How to get an element of an array inside another array? - arrays

So the only way i can think of achieving this is by putting the array inside mainArray into a variable and then indexing that. Is there an easier way?
mainArray = [ 3400, "Overwatch", [UIButton(), UIButton()]] // Some buttons already made
currentButtonArray = mainArray[mainArray.count - 1] as! NSArray
for i in 0..<currentButtonArray.count {
buttonArray.append( currentButtonArray[i] as! UIButton)
}

If there is one array containing only UIButton instances, just filter it.
let mainArray : [Any] = [3400, "Overwatch", [UIButton(), UIButton()]]
if let buttonArray = mainArray.filter({$0 is [UIButton]}).first as? [UIButton] {
print(buttonArray)
}
or
let buttonArray = Array(mainArray.flatMap{$0 as? [UIButton]}.joined())
The second approach returns a non-optional empty array if there is no array of UIButton in mainArray

If the subarray is of all one type, you can append all in one go:
var buttonArray = [UIButton]()
let mainArray:[Any] = [3400, "Overwatch", [UIButton(), UIButton()]] // Some buttons already made
if let currentButtonArray = mainArray.last as? [UIButton] {
buttonArray.append(contentsOf: currentButtonArray)
}
Or you could simply write:
guard let currentButtonArray = mainArray.last as? [UIButton] else {
// do something e.g. return or break
fatalError()
}
// do stuff with array e.g. currentButtonArray.count
If you didn't know the position in the array of the nested UIButton array or if there were multiple nested button arrays then this would work:
let buttonArray = mainArray.reduce([UIButton]()){ (array, element) in if let bArray = element as? [UIButton] {
return array + bArray
}
else {
return array
}
}
Note: this is Swift 3 code.

Related

Swift: filter an array of Element1 [(String, Bool)] to return AND convert to an array of Element2 [String]?

I have an array of [(userID: String, friendBool: Bool)] that I want to filter AND convert to an array of userID's only [String] (removing the friendBool and therefore changing the element). Is there a function in Swift for doing this?
Currently, I am filtering on the array and then using a for loop on the filtered array [(userID: String, friendBool: Bool)] to convert it to an array of [String]. Is there a better way to do this?
Current Code:
let friendArray = [(userID: String, friendBool: Bool)]()
let excludeUsers = [String]()
//Updates with user actions
var userArrayForTableView = [String]()
//Filter friendArray
let newArray = friendArray.filter { (existingFriend) -> Bool in
return !excludeUsers.contains(existingFriend.userID)
}
//Convert array fro [(userID: String, friendBool: Bool)] to [String]
for existingFriend in newArray {
userArrayForTableView.append(existingFriend.userID)
}
What I'm trying to do:
//Loaded on ViewDidLoad
let friendArray = [(userID: String, friendBool: Bool)]()
let excludeUsers = [String]()
//Updates with user actions
var userArrayForTableView = [String]()
//Filter friendArray
/*
Below fitler returns an array of [(userID: String, friendBool: Bool)]...
but I want a filter to return an array of [String] for just userIDs
*/
let newArray = friendArray.filter { (existingFriend) -> Bool in
return !excludeUsers.contains(existingFriend.userID)
}
//ERROR HERE because 'newArray' is not [String]
userArrayForTableView.append(contentsOf: newArray)
What about using compactMap()?
In a certain way, it can be understood as a filter() (that you are already using) + map() (which is the loop for existingFriend in newArray in the first solution)
let userArrayForTableView = friendArray.compactMap({ (existingFriend) in
if excludeUsers.contains($0.userID) {
return nil
} else {
return existingFriend.id
}
})
In a shorter way:
let userArrayForTableView = friendArray.compactMap({ excludeUsers.contains($0.userID) ? nil : $0.userID })

How to filter Dictionary of Array Swift3.0?

I've an Dictionary which contains Array and that Array has another Dictionary ant it also has another array. How do I get the last array by using 'Dictionary.Filter'.
For Example
Dict1->Array1->Dict2->Array2.
Here I need
Array2
I want to get "DeviceLsit" Array
Check this out! Based on your screenshot, I have managed to achieve it!
func filterArray() {
let dictPlist = Dictionary<String, Any>()
if let arrKeyName = dictPlist["key"] as? Array<Dictionary<String, Any>> {
let yourSecondArray = arrKeyName.filter({ (keyDict) -> Bool in
guard let _ = keyDict["keyName"] as? Array<Any> else {
return false
}
return true
})
}
}
Hope this helps!
if you want array of DeviceLists you can got through categories and get device lists
let root: [String: Any] = ["Categories": [ ["deviceList": ["1","2","3","4"]], ["deviceList": ["5","6","7","8"]] ]]
if let categories = root["Categories"] as? [Any] {
var deviceLists: [String] = []
for cat in categories {
if let cat = cat as? [String: Any], let deviceNames = cat["deviceList"] as? [String] {
deviceLists.append(contentsOf: deviceNames)
}
}
print(deviceLists)
}
here is the short anser :
Assume that your desired Array has Any Type. you can make it as you want like String , Int etc...!
let dict = [String:[[String:[Any]]]]()
let arr = dict.flatMap({($0.value).flatMap({($0.values)})}).last
print(arr) <-- your desired Array

How to append an array in another array in Swift?

I have a JSON response whose answer I have to parse. I write the single elements into an array called courseDataArray using a for loop. After that, I want to write this newly created array into another array called combinedCourseArray with the aim to pass that on to a UITableView. Creating the first array seems to work fine.
But how can I create another array combinedCourseArray who contain all arrays of type courseDataArray?
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
var combinedCourseArray: [String: AnyObject] = [:]
combinedCourseArray[0] = courseDataArray //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
You should move the combinedCourseArray declaration outside of the array. It should be var combinedCourseArray: [[String: AnyObject]] = [[:]] since it's an array and not a dictionary.
And you should be doing
combinedCourseArray.append(courseDataArray)
instead of
combinedCourseArray[0] = courseDataArray
var FirstArray = [String]()
var SecondArray = [String:AnyObject]()
FirstArray.append(contentsOf: SecondArray.value(forKey: "key") as! [String])
First declare this combinedCourseArray array out side this loop
var combinedCourseArray: [[String: AnyObject]] = [[String: AnyObject]]()
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
combinedCourseArray.append(courseDataArray) //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
}
Just use flatMap on the outer array to translate one array into another array, possibly dropping some elements:
let courseDataArray : [[String:AnyObject?]] = result.flatMap {
guard let courseEntry = $0 as? [String:AnyObject] else {
return nil
}
return [
"courseName" : courseEntry["name"],
"courseType": courseEntry["course_type"],
"courseDate": courseEntry["cor_date"],
"courseId": courseEntry["cor_id"],
"duration": courseEntry["duration"],
"schoolId": courseEntry["sco_id"],
"status": courseEntry["status"]
]
}
Of course, the guard isn't really necessary since the input type is presumably already [[String:AnyObject]] and since you then can't have any internal failures, you can just use map instead of flatMap

How to convert from a Swift String Set to an Array

I am trying to create an array of words from a string object retrieved from Parse. The object retrieved looks like this:
Then this line of code gives this.
let joinedWords = object["Words"] as! String
How do I convert joinedWords to an Array?
If you don't care about the order, you can use flatMap on the set:
var mySet = Set<String>()
for index in 1...5 {
mySet.insert("testwords\(index)")
}
let myArray = mySet.flatMap { $0 }
print(myArray) // "["testwords5", "testwords3", "testwords4", "testwords2", "testwords1"]"
If you want the list sorted alphabetically, you can make your array a var and use sortInPlace()
var myArray = mySet.flatMap { $0 }
myArray.sortInPlace()
print(myArray) // "["testwords1", "testwords2", "testwords3", "testwords4", "testwords5"]"
If object["Words"] is AnyObject, you will have to unwrap it.
if let joinedWordsSet = object["Words"] as? Set<String> {
var joinedWordsArray = joinedWordsSet.flatMap { $0 }
myArray.sortInPlace()
print(myArray)
}
Swift 3 note: sortInPlace() has been renamed sort().
Many thanks to #JAL for so much time on chat to solve this one. This is what we came up with. Its a bodge and no doubt there is a better way!
When uploading to Parse save the set as an array.
let wordsSet = (wordList?.words?.valueForKey("wordName"))! as! NSSet
let wordsArray = Array(wordsSet)
Then it saves to Parse - looking like a set, not an array or a dictionary.
let parseWordList = PFObject(className: "WordList")
parseWordList.setObject("\(wordsArray)", forKey: "Words")
parseWordList.saveInBackgroundWithBlock { (succeeded, error) -> Void in
if succeeded {
// Do something
} else {
print("Error: \(error) \(error?.userInfo)")
}
}
Then you can drop the [ ] off the string when its downloaded from Parse, and remove the , and add some "" and voila, there is an array that can be used e.g. to add to CoreData.
var joinedWords = object["Words"] as! String
joinedWords = String(joinedWords.characters.dropFirst())
joinedWords = String(joinedWords.characters.dropLast())
let joinedWordsArray = joinedWords.characters.split() {$0 == ","}.map{ String($0) } // Thanks #JAL!

SWIFT String? does not have a member named 'element'

I would like to know how can i fill my label from an Array
func metaDataUpdated(metaData : NSString){
var listItems: NSArray = [metaData.componentsSeparatedByString(";")]
if ([listItems.count] > 0){
println([listItems.objectAtIndex(0)])
titleSong.text = [listItems.objectAtIndex(0)]
}
}
I don't really know how to convert an array to string.
Direct conversion to Swift:
func metaDataUpdated(metaData : String) {
let listItems = metaData.componentsSeparatedByString(";")
if listItems.count > 0 {
print(listItems[0])
titleSong.text = listItems[0]
}
}
Nicer Swift:
func metaDataUpdated(metaData : String) {
let listItems = metaData.componentsSeparatedByString(";")
if let first = listItems.first {
print(first)
titleSong.text = first
}
}
Even nicer Swift, without using Foundation and without the function needing to get every component separated by ";", but only the first one (recommended):
func metaDataUpdated(metaData : String) {
if let index = metaData.characters.indexOf(";") {
let first = metaData[metaData.startIndex ..< index]
print(first)
titleSong.text = first
}
}
you cannot assign NSArray to NSString therefore you need to cast the value of this first index into a string
change this
titleSong.text = [listItems.objectAtIndex(0)]
to
titleSong.text = "\(listItems.objectAtIndex(0))"
or
titleSong.text = listItems[0] as! String
and also change this line to ([listItems.count > 0]) to (listItems.count > 0)
your code will look like this:
Note this not obj-c so remove all []
func metaDataUpdated(metaData : NSString){
var listItems: NSArray = metaData.componentsSeparatedByString(";")
if (listItems.count > 0)
{
println(listItems.objectAtIndex(0))
titleSong.text = listItems.objectAtIndex(0) as! String
}
}
Better use Swift types and objects now: Array instead of NSArray, Dictionary instead of NSDictionary, etc.
func metaDataUpdated(metaData : NSString) {
var listItems = metaData.componentsSeparatedByString(";")
if listItems.count > 0 {
print(listItems[0])
titleSong.text = listItems[0]
}
}
Here componentsSeparatedByString returns an array of strings: [String]. We then use simple index subscripting to retrieve its first value.
Note: I suppose you were trying to adapt code from Objective-C because your example was ridden with [] everywhere...
Put your to string item in "\\()".
For instance:
titleSong.text = "\\([listItems.objectAtIndex(0)])"
Not sure you need the [] brackets though

Resources