How to convert from a Swift String Set to an Array - arrays

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!

Related

Add Parse array to dictionary swift

I have some objects in parse and I am getting the data successfully as [PFObjects]. The issue is that I am trying to add the array elements [PFObjects] to a dictionary as values. But I keep getting an empty dictionary, so the values are not added to the dictionary. The dictionary count is also 0.
This is what I tried so far:
var postDictionary = [String:[AnyObject]]()
query.findObjectsInBackground(block: { (posts: [PFObject]?, error:Error?) in
if let unwrappedPosts = posts {
for posts in unwrappedPosts {
if let postText = posts.object(forKey: "title") as?String {
self.titleArray.append(postText)
print("count", self.titleArray.count) // count 10
self.postDictionary["title"]?.append(self.titleArray as AnyObject)
**try to force unwrap **
self.postDictionary["title"]!.append(self.titleArray as AnyObject), and the app crashed
for (title, text) in self.postDictionary {
print("\(title) = \(text)")
}
print("Dictionay text count",self.postDictionary.count) // count is 0
}
}
}
})
This syntax is very confusing
self.titleArray.append(postText)
self.postDictionary["title"]?.append(self.titleArray as AnyObject)
You append a string to an array and then you are going to append the array to the array in the dictionary. I guess this is not intended.
I recommend to map the title strings and set the array for key title once
var postDictionary = [String:[String]]()
query.findObjectsInBackground(block: { (posts: [PFObject]?, error:Error?) in
if let unwrappedPosts = posts {
self.titleArray = unwrappedPosts.compactMap { $0.object(forKey: "title") as? String }
self.postDictionary["title"] = self.titleArray
for (title, text) in self.postDictionary {
print("\(title) = \(text)")
}
print("Dictionay text count",self.postDictionary.count) // count is 0
}
})
Never use AnyObject if the type is more specific.
The proper way of adding to a dictionary is using updateValue because as far as i can see that you don't have the key "title" in your dictionary and you are appending values to unknown key i guess.
This should help:
titleArray.append(postText)
postDictionary.updateValue(titleArray as [AnyObject], forKey: "title")
for (key,value) in postDictionary {
print("\(key) \(value)")
}
Finally this should print:
title [posts1, posts2, posts3]

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 we can find an element from [AnyObject] type array in swift

I have [AnyObject] array
var updatedPos = [AnyObject]()
I am setting data in that according to my requirement like!
let para:NSMutableDictionary = NSMutableDictionary()
para.setValue(posId, forKey: "id")
para.setValue(posName, forKey: "job")
let jsonData = try! NSJSONSerialization.dataWithJSONObject(para, options: NSJSONWritingOptions())
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) as! String
self.updatedPos.append(jsonString)
Now in my code i have some requirement to remove the object from this array where id getting matched according to requirement Here is the code which i am trying to implement
for var i = 0; i < updatedPos.count; i++
{
let posItem = updatedPos[i]
print("Id=\(posItem)")
let pId = posItem["id"] as? String
print("secRId=\(pId)")
if removeId! == pId!
{
updatedPos.removeAtIndex(i)
}
}
Here print("Id=\(posItem)") give me output asId={"id":"51","job":"Programmer"} but here i am not able to access id from this object. here print("secRId=\(pId)") give me nil
First of all use native Swift collection types.
Second of all use types as specific as possible.
For example your [AnyObject] array can be also declared as an array of dictionaries [[String:AnyObject]]
var updatedPos = [[String:AnyObject]]()
Now create the dictionaries and add them to the array (in your example the dictionary is actually [String:String] but I keep the AnyObject values).
let para1 : [String:AnyObject] = ["id" : "51", "job" : "Programmer"]
let para2 : [String:AnyObject] = ["id" : "12", "job" : "Designer"]
updatedPos.append(para1)
updatedPos.append(para2)
If you want to remove an item by id use the filter function
let removeId = "12"
updatedPos = updatedPos.filter { $0["id"] as? String != removeId }
or alternatively
if let indexToDelete = updatedPos.indexOf{ $0["id"] as? String == removeId} {
updatedPos.removeAtIndex(indexToDelete)
}
The JSON serialization is not needed for the code you provided.
PS: Never write valueForKey: and setValue:forKey: unless you know exactly what it's doing.
After some little bit stuffs I have found the very easy and best solution for my question. And I want to do special thanks to #vadian. Because he teach me new thing here. Hey Thank you very much #vadian
Finally the answer is I had covert posItem in json Format for finding the id from Id={"id":"51","job":"Programmer"} this string
And the way is
let data = posItem.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
if let dict = json as? [String: AnyObject] {
let id = dict["id"]
if removeId! == id! as! String
{
updatedLoc.removeAtIndex(i)
}
}
}
catch {
print(error)
}

JSON To Array in Swift

I'm Using Swift2.0+, SwiftyJSON, Alamofire
I Got the Value let stringJSON:JSON = ["a1","a2","a3"] from Server
But If I Check stringJSON[0],Then it's null
When I debugPrint(stringJSON), Then it's ["a1","a2","a3"]
How Can I got the value stringJSON[0] //"a1" ?
Do I Have To Convert From JSON To Another?
The correct syntax is
let stringJSON:JSON = ["a1","a2","a3"]
if let firstValue = stringJSON.array?.first {
print(firstValue) // a1
}
Update
Since the value actually contains this string "[\"a1\/a1\",\"a2\/a2\",\"a3\"]" and you cannot fix this on the server side here it is a workaround.
if let words = stringJSON.string?.characters.dropFirst().dropLast().split(",").map(String.init) {
let word = String(words[0].characters.dropFirst().dropLast())
print(word) // a1
}
if let x = stringJSON[0].string{
print(x)
}
Since the server is not returning an Array, but a String, you need to convert that into an Array of Strings like this:
let string = stringJSON.string
let array = string.stringByReplacingOccurrencesOfString("[", withString: "")
.stringByReplacingOccurrencesOfString("]", withString: "")
.stringByReplacingOccurrencesOfString("\"", withString: "")
.componentsSeparatedByString(",")
stringJSONIf it is a string type, you can like this to solve:
extension String {
var parseJSONString: AnyObject? {
var any: AnyObject?
let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
do{
any = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers)
}catch let error as NSError{
print("error: \(error)")
}
return any
}
and use it like this:
let strArr = stringJSON.stringvalue.parseJSONString as! Array<String>

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