How Would I Create a Constant That Could Be One of Several Strings Depending on Conditions

Assinging constant value to one among different variables based on a condition

You can technically do:

marks = (Grade > marks) ? (passMark = marks) : (failedMark = marks);

Which will give you what you want, but the problem is marks is just being assigned the same value it already had because you cannot just have no variable assignment when using the ternary operator.

This is a bit confusing, so I don't know if I condone this.

Java Docs Source for conditional operator:

It is a compile-time error for either the second or the third operand expression to be an invocation of a void method.

This is relevant because say you extract the passMark = marks to a method:

public static void passMarks(){
passMark = marks;
}

And try to use it like:

(Grade > marks) ? passMarks() : failedMarks();

It would be a void method because you do not actually need to return anything, your logic is already complete. So this conditional operator only works because we are basically giving it a dummy return value that we do not need because void is against the specifications.

Now you could always add a return that means something like

public static String passMarks(){
passMark = marks;
return "PASSED";
}

And use it like this:

String passed = (Grade > marks) ? passMarks() : failedMarks();

Which will set the values AND return the String that says PASSED or FAILED, and do multiple things at once!

Note: I am pretending passMark and marks are class variables accessible from the method without passing it for ease of explanation.

Set multiple const values based on conditional

I would say nothing wrong with using let overall, however the answer to your question is:

const [a, b] = fooBar ? ["foo", "bar"] : ["baz", "Hello world!"]

In this case array destructuring can be used. So we create variables to access array item by index (a is #0, b is #1)

Conditionally initializing a constant in Javascript

Your problem, as you know, is that a const has to be intialised in the same expression that it was declared in.

This doesn't mean that the value you assign to your constant has to be a literal value. It could be any valid expression really - ternary:

const x = IsSomeValueTrue() ? 1 : 2;

Or maybe just assign it to the value of a variable?

let y = 1;
if(IsSomeValueTrue()) {
y = 2;
}

const x = y;

You could of course assign it to the return value of a function, too:

function getConstantValue() {
return 3;
}

const x = getConstantValue();

So there's plenty of ways to make the value dynamic, you just have to make sure it's only assigned in one place.

Fill new column based on conditions defined in a string

Here a solution to convert your condition to a python function and then applying it to the rows of your DataFrame:

import re

condition_string = "colA='yes' & colB='yes' & (colC='yes' | colD='yes'): 'Yes', colA='no' & colB='no' & (colC='no' | colD='no'): 'No', ELSE : 'UNKNOWN'"

# formatting string as python function apply_cond
for col in df.columns:
condition_string = re.sub(rf"(\W|^){col}(\W|$)", rf"\1row['{col}']\2", condition_string)
condition_string = re.sub(rf"row\['{col}'\]\s*=(?!=)", f"row['{col}']==", condition_string)

cond_form = re.sub(r'(:[^[(]+), (?!ELSE)', r'\1\n\telif ', condition_string) \
.replace(": ", ":\n\t\treturn ") \
.replace("&", "and") \
.replace('|', 'or')
cond_form = re.sub(r", ELSE\s*:", "\n\telse:", cond_form)
function_def = "def apply_cond(row):\n\tif " + cond_form
#print(function_def) # uncomment to see how the function is defined

# executing the function definition of apply_cond
exec(function_def)

# applying the function to each row
df["result"]=df.apply(lambda x: apply_cond(x), axis=1)

print(df)

Output:

     ID colA colB colC colD   result
0 AB01 yes NaN yes yes UNKNOWN
1 AB02 yes yes yes no Yes
2 AB03 yes yes yes yes Yes
3 AB03 no no no no No
4 AB04 no no no NaN No
5 AB05 yes NaN NaN no UNKNOWN
6 AB06 NaN yes NaN NaN UNKNOWN

You might want to adapt string formatting depending on condition_string (I did it quickly, there might be some unsupported combinations) but if you get those strings automatically it will save you from defining them all over again.

How Should I Define/Declare String Constants

Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.

When you define a global string constant that is not subject to change, I would recommend you make it a const array:

const char product_name[] = "The program version 3";

Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.

Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:

int main() {
const char *s1 = "world";
printf("Hello %s\n", s1);
return 0;
}

If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.

Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.

Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.

Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:

char *p = strchr("Hello World\n", 'H');

This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness.

How to set a value to variable based on multiple conditions using Java Streams API?

It could be done with Stream IPA in a single statement and without multiline lambdas, nested conditions and impure function that changes the state outside the lambda.

My approach is to introduce an enum which elements correspond to all possible outcomes with its constants EMPTY, SILICON, RADIUM, BOTH.

All the return values apart from empty string can be obtained by invoking the method name() derived from the java.lang.Enum. And only to caver the case with empty string, I've added getName() method.

Note that since Java 16 enums can be declared locally inside a method.

The logic of the stream pipeline is the following:

  • stream elements turns into a stream of string;
  • gets filtered and transformed into a stream of enum constants;
  • reduction is done on the enum members;
  • optional of enum turs into an optional of string.

Implementation can look like this:

public static String resolve(List<Element> elements) {
return elements.stream()
.map(Element::getName)
.map(String::toUpperCase)
.filter(str -> str.equals("SILICON") || str.equals("RADIUM"))
.map(Elements::valueOf)
.reduce((result, next) -> result == Elements.BOTH || result != next ? Elements.BOTH : next)
.map(Elements::getName)
.orElse("");
}

enum

enum Elements {EMPTY, SILICON, RADIUM, BOTH;
String getName() {
return this == EMPTY ? "" : name(); // note name() declared in the java.lang.Enum as final and can't be overridden
}
}

main

public static void main(String[] args) {
System.out.println(resolve(List.of(new Element("Silicon"), new Element("Lithium"))));
System.out.println(resolve(List.of(new Element("Silicon"), new Element("Radium"))));
System.out.println(resolve(List.of(new Element("Ferrum"), new Element("Oxygen"), new Element("Aurum")))
.isEmpty() + " - no target elements"); // output is an empty string
}

output

SILICON
BOTH
true - no target elements

Note:

  • Although with streams you can produce the result in O(n) time iterative approach might be better for this task. Think about it this way: if you have a list of 10.000 elements in the list and it starts with "SILICON" and "RADIUM". You could easily break the loop and return "BOTH".
  • Stateful operations in the streams has to be avoided according to the documentation, also to understand why javadoc warns against stateful streams you might take a look at this question. If you want to play around with AtomicReference it's totally fine, just keep in mind that this approach is not considered to be good practice.

I guess if I had implemented such a method with streams, the overall logic would be the same as above, but without utilizing an enum. Since only a single object is needed it's a reduction, so I'll apply reduce() on a stream of strings, extract the reduction logic with all the conditions to a separate method. Normally, lambdas have to be well-readable one-liners.

Declaring a constant in swift

Example

let myConstant = getSomeValueFromMethod()

This is what it means that the value doesn't have to be known at compile time...



Related Topics



Leave a reply



Submit