Elegant way to check if multiple strings are empty - string

How can I check if multiple strings are empty in an elegant way? This is how I currently do it:
//if one required field is empty, close the connection
if (registerRequest.Email == "") ||
(registerRequest.PhoneNumber == "")||
(registerRequest.NachName =="") ||
(registerRequest.VorName =="") ||
(registerRequest.Password =="") ||
(registerRequest.VerificationId ==""){
//Could not proceed
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}

Note: You may use the solution below if you keep the "is-valid" condition in your handler, and also if you separate your condition into another function or method.
You can create a simple helper function, which has a variadic parameter, and you can call it with any number of string values:
func containsEmpty(ss ...string) bool {
for _, s := range ss {
if s == "" {
return true
}
}
return false
}
Example using it:
if containsEmpty("one", "two", "") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
if containsEmpty("one", "two", "three") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
Output of the above (try it on the Go Playground):
One is empty!
All is non-empty.
Your example would look like this:
if containsEmpty(registerRequest.Email,
registerRequest.PhoneNumber,
registerRequest.NachName,
registerRequest.VorName,
registerRequest.Password,
registerRequest.VerificationId) {
// One of the listed strings is empty
}
Also registerRequest is a kinda long name, it could be shortened to like r. If you can't or don't want to rename it in the surrounding code and if you want to shorten the condition, you could also do something like this:
If registerRequest is a pointer (or interface), you could also write:
if r := registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}
Actually you can do this even if registerRequest is not a pointer, but then the struct will be copied. If registerRequest is a struct, then you can take its address to avoid having to copy it like this:
if r := &registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}

As Mario Santini mentioned in comment, a way to increase testability, encapsulate this logic, and decouple it from your handler method (which judging by the number of fields looks like it is at risk of changing at a different rate than your handler) could be to put this logic in a function:
func validRequest(registerRequest ?) bool {
return registerRequest.Email == "" ||
registerRequest.PhoneNumber == "" ||
registerRequest.NachName == "" ||
registerRequest.VorName == "" ||
registerRequest.Password == "" ||
registerRequest.VerificationId == ""
}
This now supports very focused, table driven tests, that can exercise what it means to be a valid request independent of any method involving writing headers.
It allows you to verify the valid/invalid path of your enclosing function, but to have very focused tests here. It also allows you to change what it means to be a valid request and verify it independent of your enclosing function.

You can use a switch:
switch "" {
case registerRequest.Email,
registerRequest.NachName,
registerRequest.Password,
registerRequest.PhoneNumber,
registerRequest.VerificationId,
registerRequest.VorName:
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}
https://golang.org/ref/spec#Switch_statements

Related

How to check if a variable exists and its value in one if loop in nodejs

I have to check if a variable exists and then if exists, then if its value is this do something. How can I make both in one single if loop
if (process.env.MODULE) {
if (process.env.MODULE.includes("reRun")) {
// Do something
}
}
How can I combine both if loop. So if MODULE value is not defined, it should not return any error. If its defined and its value is reRun, then only it has to do something
You can combine two boolean expression using logical operators like && (AND) and || (OR)
if (process.env.MODULE && process.env.MODULE.includes('reRun)) {
// do something
}

If statements not working with JSON array

I have a JSON file of 2 discord client IDs `{
{
"premium": [
"a random string of numbers that is a client id",
"a random string of numbers that is a client id"
]
}
I have tried to access these client IDs to do things in the program using a for loop + if statement:
for(i in premium.premium){
if(premium.premium[i] === msg.author.id){
//do some stuff
}else{
//do some stuff
When the program is ran, it runs the for loop and goes to the else first and runs the code in there (not supposed to happen), then runs the code in the if twice. But there are only 2 client IDs and the for loop has ran 3 times, and the first time it runs it goes instantly to the else even though the person who sent the message has their client ID in the JSON file.
How can I fix this? Any help is greatly appreciated.
You may want to add a return statement within your for loop. Otherwise, the loop will continue running until a condition has been met, or it has nothing else to loop over. See the documentation on for loops here.
For example, here it is without return statements:
const json = {
"premium": [
"aaa-1",
"bbb-1"
]
}
for (i in json.premium) {
if (json.premium[i] === "aaa-1") {
console.log("this is aaa-1!!!!")
} else {
console.log("this is not what you're looking for-1...")
}
}
And here it is with return statements:
const json = {
"premium": [
"aaa-2",
"bbb-2"
]
}
function loopOverJson() {
for (i in json.premium) {
if (json.premium[i] === "aaa-2") {
console.log("this is aaa-2!!!!")
return
} else {
console.log("this is not what you're looking for-2...")
return
}
}
}
loopOverJson()
Note: without wrapping the above in a function, the console will show: "Syntax Error: Illegal return statement."
for(i in premium.premium){
if(premium.premium[i] === msg.author.id){
//do some stuff
} else{
//do some stuff
}
}
1) It will loop through all your premium.premium entries. If there are 3 entries it will execute three times. You could use a break statement if you want to exit the loop once a match is found.
2) You should check the type of your msg.author.id. Since you are using the strict comparison operator === it will evaluate to false if your msg.author.id is an integer since you are comparing to a string (based on your provided json).
Use implicit casting: if (premium.premium[i] == msg.author.id)
Use explicit casting: if (premium.premium[i] === String(msg.author.id))
The really fun and easy way to solve problems like this is to use the built-in Array methods like map, reduce or filter. Then you don't have to worry about your iterator values.
eg.
const doSomethingAuthorRelated = (el) => console.log(el, 'whoohoo!');
const authors = premiums
.filter((el) => el === msg.author.id)
.map(doSomethingAuthorRelated);
As John Lonowski points out in the comment link, using for ... in for JavaScript arrays is not reliable, because its designed to iterate over Object properties, so you can't be really sure what its iterating on, unless you've clearly defined the data and are working in an environment where you know no other library has mucked with the Array object.

How to use if let with another statement in swift?

If want to both assign a string and check that its not empty in Swift.
if let alternative3Text = attributes.stringForKey("choiceThree") && alternative3Text != "" {
// do stuff with alternative3Text
}
Is this possible in Swift, or do i have to do a nested if-statement?
Update: As of Swift 3 (Xcode 8), additional clauses are
separated by a comma, not by where:
if let alternative3Text = attributes.string(forKey: "choiceThree"),
alternative3Text != "" {
// do stuff with alternative3Text
}
Update: As of Swift 1.2 (Xcode 6.3 beta), you can combine
optional binding with additional conditions:
if let alternative3Text = attributes.stringForKey("choiceThree") where alternative3Text != "" {
// do stuff with alternative3Text
}
Using switch-case still works but is not necessary anymore for this purpose.
Old answer:
It is not possible with an if statement, but with switch.
A switch case can use a where clause to check for additional conditions
(documentation).
Assuming (from your question) that attributes.stringForKey("choiceThree") returns
String?, the following would work:
switch (attributes.stringForKey("choiceThree")) {
case .Some(let alternative3Text) where alternative3Text != "":
// alternative3Text is the unwrapped String here
default:
break
}
No, you can't require additional expressions to be true in an if let statement. You will need to add additional code to do this in either the form of a nested if statement as you've already mentioned, or in some other way. If your only requirement is to keep this statement looking clean and wouldn't mind moving some of the logic elsewhere, you could always make an extension to what ever type your attributes variable is to add this functionality.
Here's an example if attributes was an instance of NSUserDefaults. (just because it already contains a stringForKey() instance method.)
extension NSUserDefaults {
func nonEmptyStringForKey(key: String) -> String? {
let full = self.stringForKey(key)
return full != "" ? full : nil
}
}
And then use it like this
if let alternative3Text = attributes.nonEmptyStringForKey("choiceThree") {
// stuff
}

Compare enum without considering its arguments

Let me make this clear, I have this enum:
enum Token {
Number(v:Float);
Identifier(v:String);
TString(v:String);
Var;
Assign;
Division;
// and so on
}
I want to check if the value of a variable is an Identifier, but this doesn't work:
if(tk == Token.Identifier) {
It only allows me to compare the values if I pass arguments:
if(tk == Token.Identifier('test')) {
But this will only match if the identifier is 'test', but I want to match any identifier.
Type.enumConstructor(tk) == "Identifier"
Read the Type doc for more methods on enum.
Update (2019-02-04):
At the time of writing this answer it was still Haxe 2.06. Much have changed since then.
At this moment, for Haxe 3 (or 4), I would recommend pattern matching, specifically using single pattern check instead:
if (tk.match(Identifier(_)) ...
which is a short hand for
if (switch tk { case Identifier(_): true; case _: false; }) ...
_ is the wildcard that matches anything.
alternatively:
static function isIdentifier(token : Token) return switch(token) { case Token.Identifier(_): true; default: false; }
Using "using" you should also be able to do:
if(tk.isIdentifier()) {
Or even:
tk.match(Token.Identifier(_));

How does one return from a groovy closure and stop its execution?

I would like to return from a closure, like one would if using a break statement in a loop.
For example:
largeListOfElements.each{ element->
if(element == specificElement){
// do some work
return // but this will only leave this iteration and start the next
}
}
In the above if statement I would like to stop iterating through the list and leave the closure to avoid unnecessary iterations.
I've seen a solution where an exception is thrown within the closure and caught outside, but I'm not too fond of that solution.
Are there any solutions to this, other than changing the code to avoid this kind of algorithm?
I think you want to use find instead of each (at least for the specified example). Closures don't directly support break.
Under the covers, groovy doesn't actually use a closure either for find, it uses a for loop.
Alternatively, you could write your own enhanced version of find/each iterator that takes a conditional test closure, and another closure to call if a match is found, having it break if a match is met.
Here's an example:
Object.metaClass.eachBreak = { ifClosure, workClosure ->
for (Iterator iter = delegate.iterator(); iter.hasNext();) {
def value = iter.next()
if (ifClosure.call(value)) {
workClosure.call(value)
break
}
}
}
def a = ["foo", "bar", "baz", "qux"]
a.eachBreak( { it.startsWith("b") } ) {
println "working on $it"
}
// prints "working on bar"
I think you're working on the wrong level of abstraction. The .each block does exactly what it says: it executes the closure once for each element. What you probably want instead is to use List.indexOf to find the right specificElement, and then do the work you need to do on it.
If you want to process all elements until a specific one was found you could also do something like this:
largeListOfElements.find { element ->
// do some work
element == specificElement
}
Although you can use this with any kind of "break condition".
I just used this to process the first n elements of a collection by returning
counter++ >= n
at the end of the closure.
As I understand groovy, the way to shortcut these kinds of loops would be to throw a user-defined exception. I don't know what the syntax would be (not a grrovy programmer), but groovy runs on the JVM so it would be something something like:
class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}}
try { x.each{ if(it.isOk()) throw new ThisOne(it); false} }
catch(ThisOne x) { print x.foo + " is ok"; }
After paulmurray's answer I wasn't sure myself what would happen with an Exception thrown from within a closure, so I whipped up a JUnit Test Case that is easy to think about:
class TestCaseForThrowingExceptionFromInsideClosure {
#Test
void testEearlyReturnViaException() {
try {
[ 'a', 'b', 'c', 'd' ].each {
System.out.println(it)
if (it == 'c') {
throw new Exception("Found c")
}
}
}
catch (Exception exe) {
System.out.println(exe.message)
}
}
}
The output of the above is:
a
b
c
Found c
But remember that "one should NOT use Exceptions for flow control", see in particular this Stack Overflow question: Why not use exceptions as regular flow of control?
So the above solution is less than ideal in any case. Just use:
class TestCaseForThrowingExceptionFromInsideClosure {
#Test
void testEarlyReturnViaFind() {
def curSolution
[ 'a', 'b', 'c', 'd' ].find {
System.out.println(it)
curSolution = it
return (it == 'c') // if true is returned, find() stops
}
System.out.println("Found ${curSolution}")
}
}
The output of the above is also:
a
b
c
Found c
Today I faced a similar problem while working with each closure. I wanted to break the flow of execution based on my condition but couldn't do it.
The easiest way to do in groovy is to use any() on a list instead of each if you wish to return a boolean based on some condition.
Good ole for loop still works in Groovy for your use case
for (element in largeListOfElements) {
if(element == specificElement){
// do some work
return
}
}

Resources