I am trying to implement some code that will automatically rename a users inputted name if the name they enter has already been submitted. I have it working to some extent, however the issue is that if the loop iterates over more than once, then you end up with the name being renamed to something like this 'Clothes (1) (2) (3)'
Here is the code that I have at the moment:
if nameLength == 0 {
fade()
entryWarningLabel.text = "Please enter a transaction name."
} else if arrayObject.paymentsArray().containsObject(transactionName) == true {
if autoAdjust == true {
var index = 1
while arrayObject.paymentsArray().containsObject(transactionName) == true {
transactionName = "\(transactionName) (\(index))"
index = index + 1
}
popToVC()
enterButtonCode()
} else {
fade()
entryWarningLabel.text = "You already have a transaction named '\(transactionName)'."
}
} else if nameLength > 0 {
popToVC()
enterButtonCode()
}
The first else if is the relevant part of the code.
How can I rename transactionName without ending up with multiple values in brackets?
This is because you are using transactionName that may have been modified by the prior iterations of the loop. You should use the original transactionName instead:
let originalName = transactionName;
while arrayObject.paymentsArray().containsObject(transactionName) {
transactionName = "\(originalName) (\(index))"
index = index + 1
}
}
Related
Such a weird question, but I set up this code in a playground:
let currentNumber = "1999999999"
let absNumber = abs(Double(currentNumber)!)
var digitCount = 0
if absNumber > 999999999 {
for n in currentNumber {
if n.isNumber {
digitCount += 1
} else {
break
}
print(digitCount)
}
}
As written, this code gets evaluated and my for loop runs...however, if is set my string to "-1999999999", the for loop doesn't run. The absolute value of -1999999999 is 100% greater than 999999999, so what did I miss?
The thing you did not understand is the control flow operator. You can get the expected behavior just change a single line:
if n.isNumber {
digitCount += 1
} else {
break // here change to continue
}
to this:
if n.isNumber {
digitCount += 1
} else {
continue
}
However, I highly recommend you try LLDB in an Xcode Project, either a Commandline tool or app. The stepover tool is quite useful for such a logical problem.
It seems like there should be a simple way to do this:
for each token
look it up in a dictionary
if it's there already, increment the value by 1
else create it and set value to 1
I can do this with
for token in tokens {
if let count = myDict[token] {
myDict[token] = count + 1
} else {
myDict[token] = 1
}
But it seems like there must be a more elegant, single line way to do this?
You can use the ternary operator:
for token in tokens {
myDict[token] = myDict[token] ? myDict[token]! + 1 : 1
}
Better yet, use nil coalescing:
for token in tokens {
myDict[token] = (myDict[token] ?? 0) + 1
}
And to put the whole thing in one line:
tokens.forEach { myDict[$0] = (myDict[$0] ?? 0) + 1 }
And with Swift 4 (thanks Hamish), it can be a little shorter with:
tokens.forEach { myDict[$0, default: 0] += 1 }
tokens.map{ myDict[$0] = (myDict[$0] ?? 0) + 1 }
I'm completing the CS193 Stanford course, and am using Core Data to store tweets as part of a Twitter client.
However, when I find a hashmention that is existing, I want to increment the hash.count representing how many matches I have, but no matter how many matching hashmentions there are hash.count only ever stores 0 or 2 (i.e. the attribute is not functioning as persistent storage on the entity).
class HashMention: NSManagedObject {
static func findOrCreateHashMention(matching twitterInfo: Twitter.Mention, in context: NSManagedObjectContext) throws -> HashMention
{
let hash = HashMention (context: context)
let request : NSFetchRequest<HashMention> = HashMention.fetchRequest()
request.predicate = NSPredicate(format: "text =[cd] %#", twitterInfo.keyword)
do {
let matches = try context.fetch(request)
if matches.count > 0 {
//inc count
hash.count = Int32(Int(matches.count) + 1)
return hash
}
else{
hash.count = 0
print("zero hash:", twitterInfo.keyword)
hash.text = twitterInfo.keyword.lowercased()
return hash
}
}
catch{
//makes this function throw
throw error
}
}
}
So matches itself needed to be changed - but is in an array in the example above. Therefore the answer was the following:
do {
let matches = try context.fetch(request)
let mention = matches.first
if matches.count > 0 {
mention?.count = (mention?.count)! + 1
//.. more code
What's needed to get this code running?
Hi, I already have this part of code. It searches in an array of struct and delivers - if found - the index of that item:
for index in 0 ..< gSteering.count {
if gSteering[index].Ext == fileExtension.uppercaseString {
priority = index
break
}
}
I'm sure, that there is are shoreter and more elegant way in SWIFT using library functions. Any hints?
Something like
let priority = gSteering.indexOf() {
$0.Ext == fileExtension.uppercaseString
}
P.S. And if you want priority to default to maxint in case if item is not found:
let priority = gSteering.indexOf() {
$0.Ext == fileExtension.uppercaseString
} ?? Int.max
Here's one I could come up with:
if let index = (gSteering.map{ $0.Ext }).indexOf(fileExtension.uppercaseString)
{
priority = index
}
else
{
// Not found.
}
And here's another one:
let priority = gSteering.indexOf { $0.Ext == fileExtension.uppercaseString }
And here's one to get the object directly instead of the index:
// This will give you an array with all the results that match.
let priorityObj = gSteering.filter { $0.Ext == fileExtension.uppercaseString }
I'm trying to change a tuple in an array , however ,when I try
emo = (type:emo.type,strength:increaseStrength(emo.strength))
it gives me error
"cannot assign to 'let' value 'emo'
here is my code :
var emotions : [(type : String, strength: Int)] = [("happy",0),("scared",0),("tender",0),("excited",0),("sad",0)]
func increaseStrength(i:Int)->Int {
switch i {
case 0: return 1
case 1: return 2
case 2: return 3
case 3: return 0
default :return 0
}
}
#IBAction func HappyBA(sender: AnyObject) {
for emo in emotions {
if (emo.type == "happy" ){
emo = (type:emo.type,strength:increaseStrength(emo.strength))
}
}
println(emotions)
}
If there are better way to do the assignment please tell me I am so appreciated ! Thanks..
There is no point assigning to emo even if you could do it. This is not the same as replacing the corresponding object in the array - which is what you do want to do. emo is a copy; even if you were to set a property of it, it wouldn't affect the one back in the array. And certainly setting the variable would not magically read back into the array!
Here's one solution. Instead of cycling thru emotions in your for-loop, cycle thru enumerate(emotions). Now you have a tuple of an index number along with an emotion. If this is the right emotion type, write into the array via the index number.
for (ix,emo) in enumerate(emotions) {
if emo.type == "happy" {
emotions[ix] = (type:emo.type,strength:increaseStrength(emo.strength))
}
}
Or you could use map.
emotions = emotions.map {
emo in
if emo.type == "happy" {
return (type:emo.type,strength:increaseStrength(emo.strength))
} else {
return emo
}
}