Concatenating string with number in Javascript - javascript

I'm trying to create a simple calculator in Javascript. I have an array named expression
chunk[0] = 12
chunk[1] = + (the "+" sign)
chunk[1] = 5
I used a for loop to loop through the chunks (chunk[]) and join then into a single expression as follows:-
equation = ""; // To make var equation a string
for(i = 0; i <= length; i++)
{
equation = equation + expression[i];
alert(expression[i]);
}
alert(equation);
alert(expression[i]) showed values 12, + and 5.
But alert(equation) showed 125 (instead of "12+5"). I need the variable equation to be "12+5" so that I can later call eval(equation) and get the value of 12+5.
What am I doing wrong here?

if you have chunk = [ 12, '+', 5]; then you can do var eq = chunk.join(""); and then pass it to eval

What are you doing wrong? You have a small typo.
Amend the code on the question from
chunk[0] = 12
chunk[1] = '+'
chunk[1] = 5
to
chunk[0] = 12
chunk[1] = '+'
chunk[2] = 5
And everything should work.
Why this works:
Both the + and the 5 are being assigned to chunk[1], with the 5 over-writing the previous assignment ( to chunk[1]) of +. This also explains why the concatenated value displayed is 125
In order, the first assignment results in a collection with
a member chunk[0] and a content of 12
The second assignment adds a new member, and results in a collection with
a member chunk[0] whose content is 12
a member chunk[1] whose content is +
The third assignment overwrites the 2nd member, and results in a collection with
a member chunk[0] whose content is 12
a member chunk[1] whose content is 5
The concatenation of all the chunks == 125
Desired concatenation == 12+5

Related

TypeScript: How to replace a particular number in a string (a combination of numerical and non-numerical values), and then update its value?

I asked a similar question here TypeScript: How to replace a particular number in a string, and then update its value?
Really appreciate the answers there. It answered my questions.
I am run into a new issue. Thought it s more helpful to raise a new question while referring to the old question.
I have a column that is full of 10-digits string.
Sometimes that entire 10-digits only contain numerical values (e.g. 3345678901), but sometimes there is dash included (e.g. 3345678---)
I would like to be able to:
Input an index number X
Locate the corresponding number in the string
Add or subtract a particular number A to/from that number to update the string
Update the string
Example 1 (all numerical): 3345678901
Input index number "4"
The corresponding number is 6
Increase that number by +2 to 8
Update the string to 3345878901
Example 2 (numerical & non-numerical): 3345678---
Input index number "4"
The corresponding number is 6
Increase that number by +2 to 8
Update the string to 3345878---
Example 3 (numerical & non-numerical): 3345678---
Input index number "7"
The corresponding value is -
Increase (or rather, update) that number by +2 to 2
Update the string to 33458782--
For example 1, I know I could do following (as a contributor from the OG post has pointed out):
const givenStr = "3345678901";
let givenStrArray = givenStr.split('').map(Number);
const inputIndex = 4;
const increaseAmount = 2;
givenStrNumber += increaseAmount
console.log(givenStrNumber);
But, how do I go about Example 2 and 3 though? Since there are string '-' involved? In this case map(Number) would lead to Null values that would break the code.
Any help would be greatly appreciated!
Check for NaN. This is a tiny snippet that would give you a hint:
// ...
// ...
const increment = 2;
let givenStrArray =
givenStr
.split('')
.map((digiit) => isNaN(digit) ? increment : Number(digit + increment);
// ...
// ...
Here's a simple little snippet. Break the sting apart, map through each item, when we find the index we need to update we update it and return it, then join them all back together.
Multiple conditional ternary operator have been used here, you can find out more about how they work here: Conditional (ternary) operator
const givenStr = "334567----",
inputIndex = 6,
increaseAmount = 2
let givenNumber = givenStr
.split('')
.map((v,i) => i === inputIndex ? isNaN(v) ? increaseAmount : +v + increaseAmount : v)
.join('')
console.log(givenNumber);
This should do the trick
let str = '3345678---'
let NumericStrArray = str.split('').map(x => Number.isNaN(Number(x)) ? x: Number(x))
let ipIndex = 7
let incAmount = 2
let val = NumericStrArray[ipIndex]
NumericStrArray[ipIndex] = typeof val === 'string' ? incAmount : val + incAmount
let result = NumericStrArray.join('')

How do I split multiline cells into arrays for Google Sheets?

I keep a spreadsheet of the titles and issue numbers I've read for various comics. I want to have a column that provides the count of the issues read for each title. Some titles have issue numbers in multiple lines. For example, the run of Avengers starting in 2016 has the following issue numbers listed in one cell, each range on a new line within the cell:
#1-11
#1.1-5.1
#1MU
#672-676
I tried to write a script that would separate each line into an array item, and then for each item in the array, extract the numbers using regular expressions to perform calculations to determine the total count. (The count of the above issues is 22, but the problem is getting the script to determine that for me and for the other titles as I update issue numbers.)
Here's what I have so far:
function calcIssueCount(x) {
// Set initial value to 0:
var issueCount = 0;
// Make an array from the lines of the cell
// split by the line break:
var box = x.split("\n");
for (var line in box) {
// Determine if the line includes a
// range of issue numbers, indicated
// by presence of a hyphen:
if ("-" in line === True) {
// Remove the # symbol from the string:
line = line.replace("#","");
// Extract the number before the hyphen
// and delete the hyphen:
var a = line(/[0-9}+\.|[0-9]+-/);
a = a.replace("-","");
// Extract the number after the hyphen
// and delete the hyphen:
var b = line(/-[0-9}+\.|[0-9]+/);
b = b.replace("-","");
// Turn a and b into numbers:
a = number(a)
b = number(b)
// Subtract the range start from the
// range end:
var c = b - a;
// Add 1 because a range of 1-5 includes 5
// issues, while 5-1 is only 4:
c += 1;
// Update the count for the number of
// issues in the cell by adding the
// line's value:
issueCount += c;
}
else {
// If there's no hyphen, there's no
// range; the count of issues on the
// line is 1:
issueCount += 1;
}
}
}
calcIssueCount(x) would have x as the cell name (e.g., D15).
I'm likely making mistakes all over the place, but I especially think I'm not understanding something about getting the cell data into the array into the first place. What am I missing here?
You want to retrieve "22" from the following value in a cell.
#1-11
#1.1-5.1
#1MU
#672-676
As the logic for retrieving "22" from the value, I understood as follows.
Retrieve 1 and 11 from #1-11.
Retrieve 1.1 and 5.1 from #1.1-5.1.
Retrieve 672 and 676 from #672-676.
Subtract before number from after number for each line.
Add 1 to all lines.
For the line without -, add only 1.
From above logic, (11 - 1 + 1) + (5.1 - 1.1 + 1) + (1) + (676 - 672 + 1) = 22 can be obtained. If my understanding of your logic is correct, how about the modification like below?
Modification points :
When for (var line in box) { is used, each element can be retrieved by box[line].
In this modicication, I used forEach.
In Javascript, the boolean express "true" and "false".
Line is not an object. So "-" in line occurs an error.
In this modification, I used indexOf().
In Javascript, number() is Number().
When you want to use calcIssueCount(x) as a custom function, in your current script, no values are returned. So if you want to retrieve issueCount, please add return issueCount.
I couldn't understand about the function of line(/[0-9}+\.|[0-9]+-/). I'm sorry for this.
In my modification, I retrieved both the before and after numbers using a regex of ([0-9.]+)-([0-9.]+). I think that there are several solutions for your situation. So please think of this as one of them.
Modified script :
Pattern 1 :
In this pattern, your script was modified.
function calcIssueCount(x) {
// Set initial value to 0:
var issueCount = 0;
// Make an array from the lines of the cell
// split by the line break:
var box = x.split("\n");
box.forEach(function(e){
if (e.indexOf("-") > -1) {
var numbers = e.match(/([0-9.]+)-([0-9.]+)/);
// Extract the number before the hyphen
// and delete the hyphen:
var a = Number(numbers[1]);
// Extract the number after the hyphen
// and delete the hyphen:
var b = Number(numbers[2]);
// Subtract the range start from the
// range end:
var c = b - a;
// Add 1 because a range of 1-5 includes 5
// issues, while 5-1 is only 4:
c += 1;
// Update the count for the number of
// issues in the cell by adding the
// line's value:
issueCount += c;
} else {
// If there's no hyphen, there's no
// range; the count of issues on the
// line is 1:
issueCount += 1;
}
});
return issueCount;
}
Pattern 2 :
This is other sample script. In this pattern, the regex is not used. The result is the same with pattern 1.
function calcIssueCount(x) {
return x.split("\n").reduce(function(c, e) {
if (e.indexOf("-") > -1) {
var numbers = e.slice(1).split("-");
c += (Number(numbers[1]) - Number(numbers[0])) + 1;
} else {
c += 1;
}
return c;
}, 0);
}
Result :
Note :
In this modified script, the regex of ([0-9.]+)-([0-9.]+) is used for the sample value. If you want to use values with other patterns, please tell me. At that time, can you show me more samples?
References :
Custom Functions in Google Sheets
Array.prototype.forEach()
String.prototype.indexOf()
Number
String.prototype.match()
If I misunderstand your question, I'm sorry.

Filling in undefined value in javascript object

I'm working on a problem where the task is to write a program which reconstructs each sentence out of a set of words and prints out the original sentences.
INPUT SAMPLE:
2000 and was not However, implemented 1998 it until;9 8 3 4 1 5 7 2
And the answer is:
However, it was not implemented until 1998 and 2000
So far I got to the point where I have combined the words and number hints together as a pair value in an object. The only problem I am running into is that there is actually a missing number hint, thus one of the words has an undefined value.
How can I fill in this value?
I have tried to use .HasOwnProperty() and for-looping through to see if one of the values equals to undefined, but neither has worked. Any input would be greatly appreciated!
function encyrption(str){
var string = str.split(";");
var words = string[0].split(" ");
var hints = string[1].split(" ");
var object = {};
for(var i = 0; i < words.length; i++){
if(object[hints[i]] === undefined){
/////???
}else
object[hints[i]] = words[i];
}
return object;
}
console.info(encyrption("2000 and was not However, implemented 1998 it until;9 8 3 4 1 5 7 2"));
I'd do something like that, just guessing that the missing hint is the last word, and that will always be the sixth position. If that's not the case I'd need more information about the problem test cases to solve it.
function encyrption(str){
var string = str.split(";");
var words = string[0].split(" ");
var hints = string[1].split(" ");
var hints_sorted = hints.concat().sort();
var missing_hint;
var object = {};
for(var i = 0; i < words.length; i++) {
if(hints_sorted[i] != i+1) {
missing_hint = (i+1).toString();
break;
}
}
hints.push(missing_hint);
for(var i = 0; i < words.length; i++){
object[hints[i]] = words[i];
}
return object;
}
console.info(encyrption("2000 and was not However, implemented 1998 it until;9 8 3 4 1 5 7 2"));
//Result: However, it was not implemented until 1998 and 2000
There you have a small explanation:
I created the hints_sorted array, which is a copy of the hints one, but sorted, so, in our example:
hints = ['9','8','3','4','1','5','7','2'];
hints_sorted = ['1','2','3','4','5','7','8','9'];
Then, inside the for, I'm comparing the value with the index + 1 (since the index inside the loop starts at zero):
1 -> 1
2 -> 2
3 -> 3
4 -> 4
5 -> 5
7 -> 6
On the sixth element, we have 7 on our array and we are expecting 6, so it goes inside the if, we set 6 as our missing hint, and we break; the loop so it doesn't continue checking values.

Confusion with arithmetic operators in Javascript

While I do know that the following question is stupid simple, it is related to a specific situation that I have been unable to find through Google. The following code is in Javascript.
Suppose there is a variable
x = x + 1;
I can see from a tutorial that this is supposed to work. However, how are we supposed to use this variable in a calculation?
I have tried with the following codes
var name = name + 1;
alert(name);
The above outputs "NaN"; whatever that is...
var name = name + 1;
name = 2;
alert(name);
The above outputs 2 which is simply overriding the original variable.
name = prompt("input any number");
var name = name + 1
alert(name);
The above outputs the input provided + 1 as a string, i.e. 01 where the input is "0" without quotes.
I remember from a ruby lesson that we use .to_i in order to convert a string to an integer. How do we go about doing this in Javascript?
var name = name + 1;
The above code declares a new variable called name which contains whatever name contained before, plus 1. Since name only just came into existence, it doesn't have a numeric value ("Not A Number", or NaN). Adding 1 to NaN gives NaN.
+ means different things in different contexts. If the two operands are numbers, then it does addition. If one operand is a String, it does String concatenation, so
var x = "2"; // x is the String "2"
alert(x+2); // "22"
var x = 2; // x is the number 2
alert(x+2); // 4
If you want to convert a String to a number, you can do
if (x) x = parseInt(x, 10);
where the second argument is the radix (i.e. the base of the number system), and you should use it. If someone entered 02 for example, the radix prevents javascript from treating that as an octal (or other) number.
Of course, you always need to make sure your variables are defined before you use them. I bet your NaN result is coming from the variable not being defined.
Your issue is that you never initialize name. For example:
var name = 0;
alert(name); // Name is 0
name = name + 1;
alert(name); // Name is 1
If you don't initialize it, it will give you NaN: Not a Number.
To turn a string into a number, use parseInt or parseFloat:
var name = prompt("input any number"); // I input 3
name = parseFloat(name);
name = name + 1;
alert(name); // Name is 4
Use parseInt to convert a string to a number.
The line x = x + 1 says "take the existing value of x, add one to it, and store the resulting value back in x again".
The line var name = name + 1 is meaningless since name does not have an existing value when the statement is executed. It is the same as saying undefined + 1 which is NaN (Not a Number).
Here are some examples of how the + operator works in JavaScript:
1 + 2 // number + number is a number -> 3
"1" + 2 // string + anything is a string => "12"
1 + "2" // anything + string is a string => "12"
"1" + "2" // string + string is a string => "12"
NaN means "not a number". Since name has no value when it is first declared, saying "var name = name + 1" doesn't have a numerical meaning, since name is in the process of being declared when used for the first time.
In the second example, name is determined to be a string. Javascript isn't as sensitive to types as some other languages, so it uses + as a concatenation operator instead of a numerical one, since it makes more sense in context,

Strange for loop behavior in Javascript function

I have this below loop in my function
I see it loop through if x is <10 but if it is greater than 10 it fails even though the condition of y < x satisfies
function insert(x,y) {
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
}
}
This is the actual function, I am trying to visualize a insert before scenario using rapheal.js it works for insertBeforeTo(9,2) but when i try insertBeforeTo(10,2) it do not get into the loop.
function insertBeforeTo(whichElementI, insertBeforeI) {
var twhichElement = blocks[whichElementI];
blocks[whichElementI].animate({ x: blocks[insertBeforeI].attr('x') }, 1000, ">");
var shiftplusone = insertBeforeI;
for (var shift = insertBeforeI; shift < whichElementI; shift++) {
++shiftplusone;
blocks[shift].animate({ x: blocks[shiftplusone].attr('x') }, 1000, ">");// check value actually changes
}
}
Down voters: mind explaining?
Issue found: while debugging I see whichElementI and insertBeforeI values in ' '. So I assume It takes it as a string and as nnnnn and paxdiablo rightly pointed out, it takes as string instead of int so It worked for whichElementI = 9 and insertBeforeI = 2 and not whichElementI= 10 ,insertBeforeI=2.
So I used unary plus operator like +whichElementI, +insertBeforeI which fixes the issue.
Thanks
I'm guessing you are inadvertantly calling your function with string values rather than number values, that is with
insert("9", "2")
insert("10", "2")
...rather than
insert(9, 2)
insert(10, 2)
If you are getting your values from html element attributes, for example, they'll be strings.
With strings, "2" < "9" is true, but "2" < "10" is false - it does a lexicographic (dictionary) order comparison, not a numeric comparison.
If you want your function to work either way then you can change it to convert strings to numbers (I prefer to use the unary plus operator for that purpose):
function insert(x,y) {
x = +x;
y = +y;
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
}
}
I don't know what the types of whichElementI and insertBeforeI are, but convert them to numeric by *1. That should help keep some of the arithmetic in check. Might also want to check if(isNaN(some_var)==false){...} as a sanity check.
function insertBeforeTo(whichElementI, insertBeforeI) {
var twhichElement = blocks[whichElementI];
blocks[whichElementI].animate({ x: blocks[insertBeforeI].attr('x') }, 1000, ">");
var shiftplusone = insertBeforeI*1;
for (var shift = insertBeforeI*1; shift < whichElementI*1; shift++) {
++shiftplusone;
blocks[shift].animate({ x: blocks[shiftplusone].attr('x') }, 1000, ">");// check x value actually changes
}
}
You should first check what data types you're passing in to the function.
For example, all of these produce output:
insert ( 10, 2)
insert ( 9, 2)
insert ( '9', '2')
but the following does not:
insert ( '10', '2')
That's because the string '10' is actually less than the string '2'. By that, I mean that a string is not treated numerically when sorting or comparing, rather each character is compared individually, leading to things like the first twelve numbers being sequenced as:
1
10
11
12
2
3
4
5
6
7
8
9
You can see this in action with the following code (at one of the many on-line JS runners):
function insert(x,y) {
for (var shift = y; shift < x; shift++) {
//get into loop for insert (9,2) but not for insert(10,2)
document.write('x');
}
}
document.write('<br>10,2 as string: '); insert ('10','2');
document.write('<br>9,2 as string: '); insert ( '9','2');
document.write('<br>9,2 as num: '); insert ( 9, 2);
document.write('<br>10,2 as num: '); insert ( 10, 2);
which outputs:
10,2 as string:
9,2 as string: xxxxxxx
9,2 as num: xxxxxxx
10,2 as num: xxxxxxxx
If you have a string that you want treated as a number, parseInt() is one way to go, something like:
var str42 = '42';
var num42 = parseInt (str42, 10);

Categories