Replacing multiple parts of a string with switch cases js - javascript

How would I get the switch to work, such that both cases, when relevant (like below), occur? I can add return to one of the case changes and get it to work for that one, but what if I have multiple cases like below? .replace requires I assign the new value to a new variable....but how do I get that to work in a loop? I don't want to use regex/regular expressions, I want to use a switch as follows, what options do I have to get this to work?
function convertText(str) {
for (let el of str) {
switch(el) {
case "&":
str.replace("&","on") //how to fix this line...?
case "G":
str.replace("G","key") //how to fix this line...?
break;
}
}
return str
}
console.log(convertText("D&G"));
//donkey

Replace returns a new string; it does not replace the value in the string you call it on. Maybe what you want is another string variable that you modify and then return, like so:
function convertText(str) {
let result = str;
for (let el of str) {
switch(el) {
case "&":
result = result.replace("&","on");
// you may want another break here, unless fall-through is your desired behavior
case "G":
result = result.replace("G","key");
break;
}
}
return result;
}
console.log(convertText("D&G"));

You are still using replace. But you could take a new string and add the value if a cetain character is found or add the actual character to the result.
function convertText(str) {
let result = '';
for (let el of str) {
switch (el) {
case "&":
result += "on";
break;
case "G":
result += "key"
break;
default:
result += el;
}
}
return result;
}
console.log(convertText("D&G"));

Related

Is there a way to compare the strings in two arrays to see if one of them is present within the other

I have two arrays.
First one:
const triggerWord = ["what", "how", "where", "who", "can"];
Second one:
const myArray = query.split(" "); - it is created after splitting the user input in this case called query.
One is a fixed number of strings, that will not change as they are the trigger words. The other array is an input string that has been split into an array, separated by a space.
I am trying to build some sort of control flow that if any of the triggerWords are present within the myArray then it should call a specific function call the questionFunction(). However the else is that is should call the statement function. Here are the functions I have attempted:
#1: Switch Case:
switch (lowercaseMyArray.includes()) {
case triggerWord[0].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[1].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[2].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[3].toString():
questionFunction(lowercaseMyArray);
break;
default:
statementFunction(lowercaseMyArray);
#2: If statement
if (lowercaseMyArray.includes(triggerWord[0] || triggerWord[1] || triggerWord[2] || triggerWord[3], 2)) {
//alert("This is a question");
questionFunction(lowercaseMyArray);
//passe onto questionFunction
} else {
statementFunction(lowercaseMyArray);
//alert(myArray);
}
#3: Bool and If Statment
var lowercaseMyArrayBool = lowercaseMyArray.includes(triggerWord);
if (lowercaseMyArrayBool === true) {
questionFunction(lowercaseMyArray);
} else {
statementFunction(lowercaseMyArray);
}
The idea being that if it contains a trigger word then the input must be a question and therefore treated as such. However if it doesn't contain the trigger words then the input is a statement and must be treated as that.
Any help or pointers will be greatly appreciated.
Resolved this with the following code:
const intersection = triggerWord.filter(element => lowercaseMyArray.includes(element)).length;
const intersectionBool = Boolean(intersection);
I just needed to cast the filtered array length as a Boolean, to get an accurate true or false result.

Creating a unit conversion method for the number prototype

I am currently trying to create a unit conversion for metric and English scale as a method for the number prototype. Heres my code:
Number.prototype.UnitConversion = function (units){
switch (units){
case "Metric":
this = this/100;
return this;
case "English":
this = this/12;
return this;
}
}
var a = 5;
alert(a.UnitConversion("Metric"))
However I get a left side invalid argument error. Why is that?
this is immutable in JavaScript, meaning you cannot reassign it, see: this SO post. However, you could simply return the value of some calculation done on it:
Number.prototype.UnitConversion = function(units) {
switch (units){
case "Metric":
return this/100;
case "English":
return this/12;
default:
return;
}
}
var a = 5;
console.log(a.UnitConversion("Metric"))
Its because an unexpected assignment to this. Maybe try a more readable, clean solution? Something like this:
Number.prototype.UnitConversion = function (units){
let conversion;
switch (units){
case "Metric":
conversion = this/100;
break;
case "English":
conversion = this/12;
break;
//always add a default case
}
return conversion;
}

Switch is not properly working in javascript

I have a switch statement which has several cases. These cases compare values and assign a text to a variable. But when I try to execute this switch, it always executes the default case. But my condition is true.. Why?
Here is my value
Apartment
Here is my code
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case (rental_cat == "Apartment"):
rental_type='daily';
alert(rental_type);
break;
case (rental_cat == "Office"):
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
When I execute this switch, it always gives me "other"
Remove the conditional expression inside the "case" clause.
Try this:
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case "Apartment":
rental_type='daily';
alert(rental_type);
break;
case "Office":
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
switch (rental_cat) {
case (rental_cat == "Apartment"):
is equivalent to
switch (rental_cat) {
case true:
which in turn is equivalent to
if (rental_cat === true)
You don't put a condition in the case, the condition is created as an equality check between the switch and the cases, so it should be like this instead:
switch (rental_cat) {
case "Apartment":
a switch is not the right structure to deal with this problem. Here I'd recommend a map:
var rentalTypesByCat = {
DEFAULT: "other",
"Apartement": "daily",
"Office": "work_daily",
}
var rental_cat = $('#rentals_type').val();
console.log("rental_cat:", rental_cat);
var rental_type = rentalTypesByCat[rental_cat] || rentalTypesByCat.DEFAULT;
console.log("rental_type:", rental_type);
or if you need it a bit more explicit (for example because some of your mapped values may be falsy themselves):
var rental_type = rentalTypesByCat[rental_cat in rentalTypesByCat? rental_cat: "DEFAULT"];
console.log("rental_type:", rental_type);

Javascript: change test() method name

Okay, I am making a text based game and I have been using the switch command like so
switch(true){
case /run/.test(g1):
prompt("run");
break;
}
the question I have is can I can I change the name of the test() method like so
switch(true){
case /run/.act(g1):
prompt("run");
break;
}
I thought if I created a function like so it would work
function act(str){
test(str);
return;
}
but it didn't... any help would be nice.
edit: fixed switch statements
So /run/ is a regex object. It has a method called test. It doesn't have a method act, so hence you can't call act() on it.
You'll need to use prototypes:
switch{
case /run/.act(g1):
prompt("run");
break;
}
RegExp.prototype.act = function (str) {
return this.test(str);
}
Here's an explanation of Prototypes.
If you really need to do this (please see What is the XY problem?) then you can add a prototype to the RegExp object.
var regex = /fo+/;
var str = 'fooooooooooooooo';
regex.test(str); //true
RegExp.prototype.act = function(str) {
if (str == 'fooooooo' && this.test(str)) {
return true;
} else {
return false;
}
}
regex.act(str); //false (str is not 'fooooooo')
Likewise, you can make an alias (but please, don't - it works fine as it is) by simply returning this.test():
RegExp.prototype.act = function(str) {
return this.test(str);
}

Can someone explain how JSON parsers work without using eval at all?

I can't comprehend how it works without using eval - what's the secret behind this?
Edit: Could someone present a trivial example of how the tree structure is converted to an object?
JSON has a well defined grammar which is used to construct a tree which is then converted to an object.
Get Douglas Crockford's book, Javascript: the Good Parts. Appendix E includes code implementing a JSON parser. It does not use eval.
I don't know specifics but it's not really hard. Just a smart combination of reading characters and substrings, interpreting what they mean and building up an array of data while you do it. Like any other parser.
There is no secret. How do you think eval() is implemented? It uses the same techniques that you would have to use if you had to parse JSON data, i.e. effectively reimplement part of eval().
Take a look at my parser for a good idea. It isn't perfect but the code is pretty easy to follow.
public static JsonStructure Parse(string jsonText)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
var key = default(string);
var value = default(object);
foreach (var token in Lexer.Tokenize(jsonText))
{
switch (currentState)
{
case ParserState.Begin:
switch (token.Type)
{
case TokenType.BeginObject:
currentState = ParserState.Name;
current = result = new JsonObject();
break;
case TokenType.BeginArray:
currentState = ParserState.Value;
current = result = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Name:
switch (token.Type)
{
case TokenType.String:
currentState = ParserState.NameSeparator;
key = (string)token.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.NameSeparator:
switch (token.Type)
{
case TokenType.NameSeparator:
currentState = ParserState.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Value:
switch (token.Type)
{
case TokenType.Number:
case TokenType.String:
case TokenType.True:
case TokenType.False:
case TokenType.Null:
currentState = ParserState.ValueSeparator;
value = token.Value;
break;
case TokenType.BeginObject:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.Name;
current = new JsonObject();
break;
case TokenType.BeginArray:
structureStack.Push(current);
currentState = ParserState.Value;
current = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.ValueSeparator:
var jsonObject = (current as JsonObject);
var jsonArray = (current as JsonArray);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.Name;
}
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.Value;
}
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
currentState = ParserState.End;
break;
case TokenType.ValueSeparator:
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
case TokenType.ValueSeparator:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
var previousJsonArray = (previous as JsonArray);
if (previousJsonObject != null)
{
previousJsonObject.Add(keyStack.Pop(), current);
currentState = ParserState.Name;
}
if (previousJsonArray != null)
{
previousJsonArray.Add(current);
currentState = ParserState.Value;
}
if (token.Type != TokenType.ValueSeparator)
{
currentState = ParserState.End;
}
current = previous;
break;
default:
throw new JsonException(token, currentState);
}
break;
default:
break;
}
}
return result;
}
trivial example of how to convert a string with json into an object without eval:
var txt='[\'one\',\'two\']';
var re1='(\\[)'; // Any Single Character 1
var re2='(\\\'.*?\\\')'; // Single Quote String 1
var re3='(,)'; // Any Single Character 2
var re4='(\\\'.*?\\\')'; // Single Quote String 2
var re5='(\\])'; // Any Single Character 3
var p = new RegExp(re1+re2+re3+re4+re5,["i"]);
var m = p.exec(txt);
if (m != null)
{
var c1=m[1];
var s1=m[2];
var c2=m[3];
var s2=m[4];
var c3=m[5];
return [s1, s2];
}
return null;
yes this a horrible way to do it, but it does what it claims for that string :p
JSON is a native representation of data. It is simply a creative implementation of JavaScript's built-in object format. Being native, it doesn't need to be "parsed" (in the sense that the programmer needs to worry about doing it) at all.

Categories