Eliminate repetition in updating strings selected randomly within a state property - swift

First, I'm very new to Swift, and coding in general. I'm trying to use the correct terminology, so I apologize if it makes no sense. Doing my best!
Ok, so there appears to be a lot of information/answers on ways to random select strings (or integers, etc) from an array without repetition. However, in my current application, I am not using an array (I kind of am but not directly related to the question). But rather a #State designation, in which the variable has an initial value (a string with a number and letter) and is later updated when a button is pushed. The string changes to a randomly selected string from my assets folder based on the file name, which will be the same word but with a different number and letter. What is the simplest way to keep from updating to strings that have already appeared?
Example of what the code looks like:
#State var relevantWord = "bird"
Button {
let randoNum = Int.random(in: 1...5)
let x = ["a", "b", "c", "d"]
let randoLet = x.randomElement()
relevantWord = "bird" + String(randoNum) + String(randoLet)
}
So, the relevantWord variable starts as "bird2c" for example, and each time the button is pushed, it will change to "bird3b" then "bird4a" etc. I just want to keep it from repeating and return nothing when the assets are depleted. Thanks!

Related

Is there an Operation to block onComplete?

I am trying to learn reactive programming, so forgive me if I ask a silly question. I'm also open to advice on changing my design.
I am working in scala-swing to display the results of a simulator. With one setting, a chart is displayed as a histogram; with the other setting the chart is displayed as the cumulative sum. (I'm probably using the wrong word; in the first setting you might have bin1=2, bin2=5, bin3=3; in the second setting the first height is 2, the second is 2 + 5, the third is 2 + 5 + 3, etc.). The simulator can be slow, so I originally used a Future to compute it, and the set the data into the chart. I decided to try a reactive approach, so my requirements are: 1. I don't want to recreate the data when I change the display mode, and 2. I want to set the Observable once for the chart and have the chart listen to the same Observable permanently.
I got this to work when I started the chain with a PublishSubject and the Future set the data into the start of the chain. When the display mode changed, I created a new PublishSubject().map(newRenderingLogic).subscribe(theChartsObservable). I am now trying to do what looks like the "right way," but it's not working correctly. I've tried to simplify what I have done:
val textObservable: Subject[String] = PublishSubject()
textObservable.subscribe(text => {
println(s"Text: ${text}")
})
var textSubscription: Option[Subscription] = None
val start = Observable.from(Future {
"Base text"
}).cache
var i = 0
val button = new Button() {
text = "Click"
reactions += {
case event => {
i += 1
if (textSubscription.isDefined) {
textSubscription.get.unsubscribe()
}
textSubscription = Some(start.map(((j: Int) => { (base: String) => s"${base} ${j}" })(i)).subscribe(textObservable))
}
}
}
On start, an Observable is created and logic to print some text is added to it. Then, an Observable with the generated data is created and a cache is added so that the result is replayed if the next subscription comes in after its results are generated. Then, a button is created. Then on button clicks a middle observable is chained with unique logic (it's a function that creates a function to append the value of i into the string, run with the current value of i; I tried to make something that couldn't just be reused) that is supposed to change with each click. Then the first Observable is subscribed to it so that the results of the whole chain end up being printed.
In theory, the cache operation takes care of not regenerating the data, and this works once, but onComplete is called on textObservable and then it can't be used again. It works if I subscribe it like this:
textSubscription = Some(start.map(((j: Int) => { (base: String) => s"${base} ${j}" })(i)).subscribe(text => textObservable.onNext(text)))
because the call to onComplete is intercepted, but this looks wrong and I wanted to know if there was a more typical way to do this, or architect it. It makes me think that I don't understand how this is supposed to be done if there isn't an out-of-the-box operation to do this.
Thank you.
I'm not 100% sure if I got the essence of your question right, but: if you have an Observable that may complete and you want to turn it into an Observable that never completes, you can just concatenate it with Observable.never.
For example:
// will complete after emitting those three elements:
val completes = Observable.from(List(1, 2, 3))
// will emit those three elements, but will never complete:
val wontComplete = completes ++ Observable.never

Randomly select an array from group of "enabled" arrays

I have a set of four arrays. I also have an option to either enable or disable 3 of the 4 arrays (one is always enabled).
Is there a way to randomly decide which array to pull a value from (of the arrays indicated as enabled)?
I originally was aiming to make a master array and just append the content of the other enabled ones into it, but it proved a little harder than expected. I figured it would be easier to simply randomly select an array to pull the single value from as long as it was "enabled".
I'm currently pulling the value with a simple statement such as
If ????? {
return promptArrayA[desiredIndexA]
} else if { ?????
return promptArrayB[desiredIndexB]
} else if { ?????
return promptArrayC[desiredIndexC]
} else {
return promptArrayD[desiredIndexD]
I'm thinking if I had a "randomizer" that chose one of the enabled arrays, then I can use that as a constraint in an If Statement.
I'm fairly new to Swift so any help is much appreciated. Thank you
You can get the array randomly by doing:
let enabledArrays = [promptArrayA, promptArrayB, promptArrayC, promptArrayD]
let randomIndex = Int.random(in: 0..<enabledArrays.count)
let randomArray = enabledArrays[randomIndex]
return randomArray[desiredIndex]

Making text into an array - Swift

For fun I'm helping my school out by creating an app which has all class cancellations for student use. From my IT technician I got a quite complex structure containing class name, teacher, and other information looking like this:
3818,"20170217",5,752,64,"Rh",,"fr_2",,,,"iV5",,,"IS10a~IS10b~IS10c~IS10d","Z",,1,"IS10a~IS10b~IS10c~IS10d",C,201702161517,"-"
3819,"20170217",6,752,102,"Rh",,"fr",,,,"iB3","iB3",,"IT10a","Z",,0,"IT10a",,201702161517,"-"
3820,"20170217",8,752,119,"Rh",,"fr",,,,"iC1.2","iC1.2",,"IS6a","Z",,0,"IS6a",,201702161517,"-"
3821,"20170227",2,753,207,"Dd","Kru","sc",,,,"iB8","iB8",,"IS9b","Z",,2097152,"IS9b",,201702270804,"+~-"
3822,"20170227",3,753,8,"Dd",,"phH_1",,,,"iB8",,,"IS12~IT12","Z",,2097153,"IS12~IT12",C,201702270804,"-"
3823,"20170227",4,753,29,"Dd",,"phH_1",,,,"iB8",,,"IS11~IT11","Z",,2097153,"IS11~IT11",C,201702270804,"-"
3824,"20170227",5,753,30,"Dd",,"phH_1",,,,"iB8",,,"IS11~IT11","Z",,2097153,"IS11~IT11",C,201702270804,"-"
3825,"20170227",6,753,7,"Dd",,"phH_1",,,,"iB8",,,"IS12~IT12","Z",,2097153,"IS12~IT12",C,201702270804,"-"
3826,"20170227",7,753,327,"Dd",,"COV",,,,"AC1",,,,"Z",,2097153,,,201702270803,
3827,"20170227",8,753,46,"Dd",,"ph_1",,,,"iB8",,,"IS10a~IS10b~IS10c~IS10d~IT10a~IT10b","Z",,2097153,"IS10a~IS10b~IS10c~IS10d~IT10a~IT10b",C,201702270804,"-"
From this data I need to get various pieces, such as "20170217" and put them into an array for later use. How would I best do this? For anyone who cares, I added the full snippet below!
https://jsfiddle.net/pztwfsq1/
Since there is one dataset per line you can iterate through all lines. Split each line at , and you'll have an array of the information.
Similar to this (to give you an idea):
let row = "1,Peter,5,92,,Brooklyn"
let data = row.components(separatedBy: ",")
let name = data[1] // Peter
let location = data[5] // Brooklyn

Swift strings are not being stored in struct

I have a bare bones struct.
struct Transaction {
var value: String = ""
var date: String = ""
var title: String = ""
}
In my project, Transaction is used like so...
var transaction:Transaction = Transaction()
//loops 3 times
repeat {
let parsed = stringAndType(from:myParser)//-> (string:String, type:UInt8)
switch parsed.type {
case 1:
print("1 -- \(parsed.string")
transaction.value = parsed.string
case 2:
print("2 -- \(parsed.string)")
transaction.date = parsed.string
case 4:
print("4 -- \(parsed.string)")
transaction.title = parsed.string
default: break
}
} while myParser.isOk
print("Returning transaction: \(transaction)")
return transaction
In this code, a structure is created. The parser feeds the data to the switch, which assigns the parsed string to the appropriate Transaction variable. When I run the following code, the output indicates that the assignments to transaction.date and transaction.value are not sticking.
Output:
2 -- 12/22/2015
1 -- -5.00
4 -- RECURRING PAYMENT BACKBLAZE
Returning transaction: Transaction(value: "", date: "", title: "RECURRING PAYMENT BACKBLAZE")
There is complex buffering behind the scenes in stringAndType(). Looking at this as a C programmer, I really want to think that function might be the problem. However, I was under the impression that Swift strings are structures, and are therefore copy on write, just like an integer or double. Hoping you can provide insight. Thank you for your time.
Update 02/15/17
The logic in this code is functioning as expected. I think the problem here is memory management. To help drive this point, I've...
Removed the print lines from my switch
Added didSet {} to each variable in Transaction
Like so...
struct Transaction {
var value: String = "" {
didSet {
print("The VALUE has changed from \(oldValue) to \(value)")
}
}
//this is repeated appropriately for the other two variables
}
The given output rules out any logical issues. Output:
The DATE has changed from to 12/22/2015
The VALUE has changed from to -5.00
The TITLE has changed from to RECURRING PAYMENT BACKBLAZE
Returning transaction: Transaction(value: "", date: "", title: "RECURRING PAYMENT BACKBLAZE")
stringAndType() does read from an unsafe buffer, but it copies the bytes to a Data structure, and returns a string initialized from the COPIED data. I thought this would insulate me from safety issues...perhaps theres an implementation detail to String I'm missing?
Credit to #unkgd, you were on the right track with your initial answer before you retracted it. There was a logical error between the while parser.isOk loop and the parent loop (omitted to keep the code short) that was wiping Transaction between value and title being set. There was no indication of this happening in the output. The loop posted above was not looping three times, rather, it was looping once, but that single loop was iterated three times by the parent. Therefore, only the most recent parsed value was stored in the structure, in this case, title. Again, full credit to #unkgd (if you repost your answer and I will mark it as correct). Thanks to everyone for their ideas.

Swift: Indirect access / mutable

I need to go to a referenced structure:
class SearchKnot {
var isWord : Bool = false
var text : String = ""
var toNext = Dictionary<String,SearchKnot>()
}
When inserting, I need to update values in toNext dictionary. Because I want to avoid recursion, I do it in a loop. But there I need a variable which jumps from one toNext item to the other, able to change it.
var knots = toNext
...
let newKnot = SearchKnot()
knots[s] = newKnot
The last command only changes a local copy, but I need the original to be changed. I need an indirect access. In C I would use *p where I defined it as &toNext. But in Swift?
I found a solution. I remembered old pascal days. ;-)
I don't use the last reference, but the second last. Instead of
knots[s]
I use
p.knots[s]
For hopping to the next knot, I also use
p = p.knots[s]
and could use
p.knots[s]
again. Also p.knots[s] = newKnot works, because p is local not the entire term.