Swift: Appending object inside dictionary - ios

I'd like to add my dictionary with array in it to my arrayOfDictionary, i tried the suggested answer on this link, but it didn't work for me. I'm having problem on appending object in my dictionary.
Here's my code:
func formatADate() {
var dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
var journalDictionary = Dictionary<String, [Journal]>()
for index in 0..<self.sortedJournal.count {
let dateString = dateFormatter.stringFromDate(self.sortedJournal[index].journalDate)
var oldDateString = ""
// Split Date
var dateStringArr = split(dateString){$0 == " "}
var newDateString = "\(dateStringArr[0]) \(dateStringArr[2])"
// Append journal to corresponding dates
// journalDictionary[newDateString]? += [self.sortedJournal[index]]
// journalDictionary[newDateString]!.append(self.sortedJournal[index])
journalDictionary[newDateString]?.append(self.sortedJournal[index])
// add to array of journal
if !(newDateString == oldDateString) || (oldDateString == "") {
arrayOfJournalDictionary.append(journalDictionary)
}
}
println(arrayOfJournalDictionary)
}
With this line of code, it gives me empty object.
journalDictionary[newDateString]?.append(self.sortedJournal[index])
Any suggestion on how I can accomplish/fix this? I'm pretty amateur in Swift, so any help would be appreciated! Thank you.

Woah, date magic with string splits and stuff, yeiks. You already are using NSDateFormatters, for the wrong reasons though. Since journalDate is a date, use the formatter to give you the exact string you want from that date, dont let it give you some generic string and split and concatenate and argh... NOBODY will understand what you are trying to do there.
Back to the question:
Your journalDictionary is empty, if you write
journalDictionary[newDateString]?.append(self.sortedJournal[index])
You tell the program to read at "index" newDateString and if there is something take that and append a new value to it.
Do you see the mistake already?
if there is something -> You have no logic yet to insert the initial empty [Journal] for any given key.
At some point in your code you have to set up the array like so:
journalDictionary["myKey"] = []
Or probably more likely:
if journalDictionary[newDateString] == nil {
journalDictionary[newDateString] = [self.sortedJournal[index]]
} else {
journalDictionary[newDateString]?.append(self.sortedJournal[index])
}

Related

How to split the string from an array of strings in swift

I have an array like :
dateTime = ["2018/06/25 05:32:30","2018/05/25 02:37","2018/04/25 05:32:50","2018/07/25 06:30:30"]
Need to split the strings and get the response as :
time = ["05:32:30","02:37","05:32:50","06:30:30"]
Can anyone please help on this.
you can use flatMap:
let dates = ["2018/06/25 05:32:30","2018/05/25 02:37","2018/04/25 05:32:50","2018/07/25 06:30:30"]
let times = dates.flatMap({ $0.split(separator: " ").last ?? nil })
print(times)
// prints: ["05:32:30", "02:37", "05:32:50", "06:30:30"]
Use this below solution to get the times from all elements.
let dateTime = ["2018/06/25 05:32:30","2018/05/25 02:37","2018/04/25 05:32:50","2018/07/25 06:30:30"]
let array = dateTime.map { $0.components(separatedBy: " ")[1] }
//["05:32:30", "02:37", "05:32:50", "06:30:30"]
Loops each items & use split function
let times = dateTime.compactMap { $0.split(separator: " ").last }

How to force iOS Speech API to read only numbers and recognize "one" as "1"

I want to use iOS Speech API to recognize mathematical expressions. It works okay for things like two plus four times three - reads it as 2+4*3, but when I start expression with 1 it always reads it as "One". When "One" is in the middle of expression it works as expected.
I figured out that when I set SFSpeechAudioBufferRecognitionRequest property taskHint to .search when displaying live results it recognizes 1 as "1" properly at first but at the end changes it to "One"
Is there a way to configure it to recognize only numbers?
Or just force to read "One" as "1" always?
Or the only way to fix it is to format result string on my own?
I have the same problem, but looks like there is no way to configure it.
I write this extension for my code, I'm checking every segment with this.
extension String {
var numericValue: NSNumber? {
//init number formater
let numberFormater = NumberFormatter()
//check if string is numeric
numberFormater.numberStyle = .decimal
guard let number = numberFormater.number(from: self.lowercased()) else {
//check if string is spelled number
numberFormater.numberStyle = .spellOut
//change language to spanish
//numberFormater.locale = Locale(identifier: "es")
return numberFormater.number(from: self.lowercased())
}
// return converted numeric value
return number
}
}
For example
{
let numString = "1.5"
let number = numString.numericValue //1.5
// or
let numString = "Seven"
let number = numString.numericValue //7
}

Sort Array of objects according to date

I have an NSMutableArray containing objects and its called HistoryObject, and it has properties date,name,type...etc
i can't find a proper way to sort the array from new to old date for this kind of object.if somebody would explain how can i accomplish that with example !
i have tried the following but its not working:
let sortedArray = HistoryArray.sort({$0.date.compare($1.date) == NSComparisonResult.OrderedAscending })
The date comes in the following format as String : Jun 26, 2016
Do it in this way
// Create your model
class Model {
var date:NSDate!
var name:String!
}
// Not use the NSArray, but use the swift array with sepecific type of data in it
var array = [Model]()
// fake models
for i in 0..<10 {
let model = Model()
model.date = NSDate(timeInterval: Double(i*60), sinceDate: NSDate())
model.name = "\(i)"
array.append(model)
}
// then sort using this code
let newArray = array.sort{ $0.date.timeIntervalSince1970 > $1.date.timeIntervalSince1970 }
You should try it like this,
let sortedArray = HistoryArray.sortInPlace({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending })
This works fine in Swift2.1
Hope this helps you.

How to put variable inside text field AND how to convert all elements to string NOT just 1 at a time?

This is a follow up question to How to have 10 characters total and make sure at least one character from 4 different sets is used randomly
this is my code so far
let sets = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", "1234567890", "\"-/:;()$&#.,?!'[]{}#%^\\|~<>€£¥•.,"].map { Array($0.characters) }
var randoms = sets.map { $0.random }
while randoms.count < 10 {
randoms.append(sets.random.random)
}
var convertedElems = String()
let something = randoms.shuffled()
for key in something {
convertedElems = String(key)
}
uniqueRoomID.text = randoms.shuffled()
Im getting an error saying cannot convert [Element] to type "String"
So i tried a for loop but that only converts 1 at a time when its supposed to do all 10
my other question is i tried storing a character in a variable and then setting a text field.text equal to that variable and nothing happened
What am i doing wrong here
Your randoms.shuffled() is an array of Characters. You need to convert it back into a String.
Change this:
uniqueRoomID.text = randoms.shuffled()
to this:
uniqueRoomID.text = String(randoms.shuffled())

Find Object with Property in Array

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 = ""
}
}

Resources