what is the difference between .split(" ") and ...array - javascript

I am trying to get the max and min numbers from str = "8 3 -5 42 -1 0 0 -9 4 7 4 -4"
The first method gives the correct answer using .min(...arr) but the second method using .min(arr) returns NAN. I thought the spread operator and the split method both created an array that could be passed into Math. What is the difference between the two.
function highAndLow(str){
let arr = str.split(" ")
let min = Math.min(...arr)
let max = Math.max(...arr)
return max + " " + min
}
function highAndLow2(str){
let arr = str.split(" ")
let min = Math.min(arr)
let max = Math.max(arr)
return max + " " + min
}

The Math.min/max functions accept a number as an argument. You can see in the documentation that:
The static function Math.min() returns the lowest-valued number passed into it, or NaN if any parameter isn't a number and can't be converted into one.
That is why, when you don't use the spread operator, you are passing in the array and you are getting NaN as a return value.
The Split operator:
takes a pattern and divides a String into an ordered list of substrings by searching for the pattern, puts these substrings into an array, and returns the array.
It does something completely different than the Spread operator and is used for other purposes.
I would advise you read more about the Spread operator here.

Math.min does not accept an array,
you need to destructure your array like so :
function highAndLow2(str){
let arr = str.split(" ")
let min = Math.min(...arr)
let max = Math.max(...arr)
return max + " " + min
}
which gives a result of '42 -9'

Math.min() or Math.max() does not accept an array, it is accepted as arguments. The spread operator (...arr) actually expands collected elements such as arrays into separate elements. split(" ") actually converts a string to array. If you want to get min or max value from an array then you have to use apply() like Math.min.apply(null, arr) or Math.max.apply(null, arr)

Related

Reduce wrongly returning infinity

when I try to use math power in reduce it's not working as expected and returns infinity
const array1 = [1,2,3,4];
const initialValue = 0;
const sumWithInitial = array1.reduce(
(a,b) => a + Math.pow(b, b + a),
0
);
console.log(sumWithInitial);
but if there's only 1-3 numbers in arr1 it works as intended
As others have explained, you get infinity due to going way above the limit. But if you want to get the actual result, you can use BigInt operations:
const array1 = [1n, 2n, 3n, 4n];
const initialValue = 0n;
const sumWithInitial = array1.reduce(
(a, b) => a + b**(b + a),
initialValue
);
console.log(sumWithInitial.toString());
As of the last iteration, you're exceeding the capacity of the JavaScript number type (which is an IEEE-754 double-precision binary floating point value). It has nothing to do with reduce, it's just that Math.pow(4, 4 + 531450) (the last value produced by your reduce loop) goes past the limit:
console.log(Math.pow(4, 4 + 531450));
You can see when pow will do that via the Number::exponentiate abstract operation in the specification (in the text, infinity is denoted by +βˆžπ”½, negative infinity by -βˆžπ”½). This is just a fact of trying to use a 64-bit value to try to represent a truly, truly, truly massive number.
If you need to deal with those kinds of magnitudes, and you only need integer values, you can use a BigInt as Keldan Chapman points out.

Looking for assistance writing a function for JS to complete a task

I need Write a function that makes the following calculation:
param1 + param2 - param3 + param4 – param5…
and keeps with this pattern. If
any non-numerical character is encountered, ΒΌ of its value is computed as the
numerical value. The result should truncate precision.
E.G.
function(11,’a’,2,30,’z’,3) returns 35
11 + (97/4) - 2 + 30 - (122/4) + 3
I CAN'T use String built-in functions:
endsWith()
includes()
indexOf()
lastIndexOf()
localeCompare()
match()
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
trimLeft()
trimRight()
valueOf()
Also I CAN'T use Array built-in functions
concat()
copyWithin()
every()
fill()
filter()
find()
findIndex()
forEach()
indexOf()
isArray()
join()
lastIndexOf()
map()
pop()
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()
Here's a shot:
const d = (...a) => {
let total = a[0];
for (let i = 1; i < a.length; i++) {
total += (+a[i] == a[i] ? a[i] : Math.round(a[i].charCodeAt(0) / 4)) * (i & 1 ? 1 : -1);
}
return total;
};
console.log(d(11, 'a', 2, 30, 'z', 3));
Explanation: accumulate a total starting with the first argument. If the current element isn't an integer, turn it into one and divide by 4 with rounded (not truncated) result. Finally, multiply by 1 or -1 depending on the parity of the index to alternate addition and subtraction.
PS: It's a good idea to try these problems first yourself instead of letting us have all the fun!

Square every digit of a number

I am trying to learn JavaScript but find it to be a bit confusing. I am trying to square every digit of a number
For example: run 9119 through the function, 811181 will come out, because 9^2 is 81 and 1^2 is 1.
My code:
function squareDigits(num){
return Math.pow(num[0],2) && Math.pow(num[1],2);
}
Correct code:
function squareDigits(num){
return Number(('' + num).split('').map(function (val) { return val * val;}).join(''));
}
I do not know why .map, .split, and .join was used to answer the question.
.split takes a string and splits it into an array based on the character(s) passed to it '' in this case.
So
("9119").split('') === ["9", "1", "1", "9"]
.map works like a for loop but takes a function as an argument. That function is applied to every member of the array.
So
["9", "1", "1", "9"].map(function(val) { return val * val;}) === ["81", "1", "1", "81"]
.join does the opposite of .split. It takes an Array and concatenates it into a string based on the character(s) passed to it.
So
["81", "1", "1", "81"].join('') === "811181"
Additionally, the && operator checks to see if the expressions on either side of it evaluate to true. If both expressions evaluate to true, only then will it return true. It always returns a Boolean though. I think you wanted to convert your values to string first using Number.toString() and then append them together using the + operator
return Math.pow(num[0],2).toString() + Math.pow(num[1],2).toString();
function squareDigits(num) {
// Convert the result to a number. "252525" -> 252525
return Number(
num.toString() // num === "555"
.split('') // ["5", "5", "5"]
.map(elem => elem * elem) "5" * "5" === 25 (Type coversion)
// Now we have [25, 25, 25]
.join('') // "252525"
);
}
squareDigits(555);
There are several methods of this, but the first that comes to mind is to pass the number as a string, split it, then parse the numbers, square them individually, make them strings, and paste them back together, it sounds complex but makes sense once you see it
//function takes number as an argument
function convertNumber(num){
//the toString method converts a number into a string
var number = num.toString();
//the split method splits the string into individual numbers
var arr = number.split("");
//this variable will hold the numbers that we square later
var squaredArr = [];
//the for loop iterates through everything in our array
for(var i=0; i<arr.length; i++){
//parseInt turns a string into a number
var int = parseInt(arr[i]);
//Math.pow raises integers to a given exponent, in this case 2
int = Math.pow(int, 2);
//we push the number we just made into our squared array as a string
squaredArr.push(int.toString());
}
//the function returns the numbers in the squared array after joining
//them together. You could also parseInt the array if you wanted, doing
//this as parseInt(squaredArr[0]); (this would be done after joining)
return squaredArr.join('');
}
Basically you need single digits for getting squared values.
You could take Array.from, which splits a string (which is a type with an implemented Symbol.iterator) into characters and uses an optional maping for the values.
function sqare(number) {
return +Array.from(number.toString(), v => v * v).join('');
}
console.log(sqare(9119));
try these code..
function squareDigits(n) {
return +(n.toString().split('').map(val => val * val).join(''));
}
console.log(squareDigits(4444));
here + sign is convert the string into an integer.

Firebase: When ordering by key, the argument passed to startAt(), endAt(),or equalTo() must be a string

Considering a ref with children whose keys are numbers (so that with orderByKey "Children with a key that can be parsed as a 32-bit integer come first, sorted in ascending order")
Doing:
ref.orderByKey().startAt(5)
I am getting the following error:
When ordering by key, the argument passed to startAt(), endAt(),or equalTo() must be a string
In the documentation for startAt I see:
When used in combination with orderByKey(), the value must be a string.
Can I replace this with ref.orderByKey().startAt("5")? Will that still run startAt using numerical rather than lexicographical order?
All Firebase keys are strings. If you are using implicit array coercion with numeric keys, you should strongly consider switching to position as a child property. So not:
0: {foo: 'bar'}
But:
-Kpushidgoeshere: {position: 0, foo: 'bar'}
Then you would do orderByChild('position').startAt(5) to achieve the desired result of sorting by position. Numeric key strings are inefficient and generally difficult to work with in Firebase.
In the firepad code I found methods to convert a number to/from a lexicographical string so they can safely be used as keys:
let characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
// numerical to a lexigaraphically ordered string
function revisionToId(revision) {
if (revision === 0) return 'A0';
let str = '';
while (revision > 0) {
let digit = (revision % characters.length);
str = characters[digit] + str;
revision -= digit;
revision /= characters.length;
}
let prefix = characters[str.length + 9]; // Prefix with length (starting at 'A' for length 1) to ensure the id's sort lexicographically.
return prefix + str;
}
// and reverse
function revisionFromId(revisionId) {
// assert(revisionId.length > 0 && revisionId[0] === characters[revisionId.length + 8]);
let revision = 0;
for (let i = 1; i < revisionId.length; i++) {
revision *= characters.length;
revision += characters.indexOf(revisionId[i]);
}
return revision;
}

Why do I get NaN from Maths.max?

So I am trying to get the highest number from the following test cases:
Test.assertEquals(highAndLow("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"), "542 -214");
Test.assertEquals(highAndLow("1 -1"), "1 -1");
Test.assertEquals(highAndLow("1 1"), "1 1");
So far I have the following:
function highAndLow(numbers){
var numbers;
var str;
numbers = numbers.split(' ');
str = numbers.toString();
var a = Math.max(str);
return a;
}
I get NaN. I know the .split is working ok. Could someone help me out please?
Math.max accepts a series of numbers or number as strings (Math.max calls toNumber internally for each argument). The number.toString() is not necessary in your code.
If you want to use Math.max on an arbitrary number of arguments, you can use apply.
Math.max.apply(null, numbersArray);
or spread the array as arguments using the spread operator.
Math.max(...numbersArray);
Math.max expects to be passed multiple arguments, where each argument is a number. You are passing it a string.
You probably want Math.max.apply(Math, numbers) which lets you pass an array of arguments.
When you split the string we get an array of strings. We need to make it array of numbers. For this use map(Number). Then use the following.
function highAndLow(numbers){
var numbers;
var str;
numbers = numbers.split(' ').map(Number);
var a = Math.max.apply(Math, numbers);
return a;
}

Categories

Resources