I have the below javascript which puts a list of customers into an object, then outputs then on the page.
var name = ["andrew", "vic", "casey"];
var job = ["builder", "baker", "dentist"];
var product = [111, 222, 111];
var qty = [1, 2, 3];
var data = {};
for (i = 0; i < name.length; i++) {
a = {
"name": name[i],
"job": job[i],
"product": product[i],
"qty": qty[i]
};
a['xtra-' + product[i]] = qty[i];
data[name[i]] = a;
console.log(a);
}
data = $.map(data, function (val, key) {
return val;
});
data.sort();
$.each(data, function (i, val) {
$('body').append(val.name + ' - ' + val.job + ' - ' + val.product + ' - ' + val.qty + ' - ' + (val.xtra + val.product) + '<br>');
});
With what I have so far see fiddle, I am outputting the persons name - job - product - qty.
andrew - builder - 111 - 1 - NaN<br>
vic - baker - 222 - 2 - NaN<br>
casey - dentist - 111 - 3 - NaN<br>
I am also trying to print out some extra information which is storred in my object called 'xtra-' + product[i].
This is being storred in a as you can see from the console log eg xtra-222 however, I can't get it outputting in my each statement?
I understand what I have done
val.xtra + val.product
is trying to add a number with a string and this is why it isn't working but I can't seem to get work out what syntax is required (possibly getting the last nth item) here or maybe there is another method to acheive what I want here?
In case there is any confusion I want my output to be
andrew - builder - 111 - 1 - 1
vic - baker - 222 - 2 - 2
casey - dentist - 111 - 3 - 3
Where the last 1,2,3 comes from the value 'xtra-' + product[i] stored in a
The problem is inside the .each loop, more specifically in (val.xtra + val.product).
The val object for the first run of that loop is:
Object {name: "andrew", job: "builder", product: 111, qty: 1, xtra-111: 1}
As you can see, there's no xtra key in that object, instead you have an xtra-111 key. So if you use (val['xtra-' + val.product] + val.product) you'll get the result that you need.
Here's the fixed code http://jsfiddle.net/VdVax/
in your $.each did you mean
val["xtra-" + val.product]
?
Here is a working fiddle http://jsfiddle.net/p5Zhc/3/
Related
Map Characters & Sum Ended
Description
You are given a number stored in a variable with the nameN
You are also, given a string, whose length is stored in a variable with the nameK, and the string is stored in a variable with the namestr
You have to map all lower case English characters, starting from the value stored inN.
For example, if the value stored inN = 30, then the mapping of the characters will be as follows
a-30
b-31
c-32
d-33
e-34
f-35
g-36
h-37
i-38
j-39
k-40
l-41
m-42
n-43
o-44
p-45
q-46
r-47
s-48
t-49
u-50
v-51
w-52
x-53
y-54
z-55
Finally, you have to print the sum of all the characters, present in the stringstr, according to the values mapped above
For example, if the value stored instr = "abc", then the required output will be
30 + 31 + 32 = 93, which is the required output
Input
The first line of the input contains the value stored inN
The second line of the input contains the value stored inK
The last line of the input contains the value stored in thestr
Output
Print the sum of characters, according to the values mapped, as shown in the problem statement
Sample Input 1
30
3
abc
Sample Output 1
93
Hint
In the sample test case, the value stored inN = 30, then the mapping of the characters will be as follows
a-30
b-31
c-32
d-33
e-34
f-35
g-36
h-37
i-38
j-39
k-40
l-41
m-42
n-43
o-44
p-45
q-46
r-47
s-48
t-49
u-50
v-51
w-52
x-53
y-54
z-55
Finally, you have to print the sum of all the characters, present in the stringstr, according to the values mapped above
For example, if the value stored instr = "abc", then the required output will be
30 + 31 + 32 = 93, which is the required output
code in image
function mapCharAndSum(n, str) {
let alphabet = [ ...Array(26).keys() ]
let alphabetWithValues = alphabet.map(num => [ String.fromCharCode(97 + num), n + num ])
let values = Array.from(str).map(char => alphabetWithValues.find(item => item[0] === char)[1])
return values.join(' + ') + ' = ' + values.reduce((sum, value) => sum + value)
}
console.log(mapCharAndSum(30, 'abc'))
// Output: 30 + 31 + 32 = 93
console.log(mapCharAndSum(0, 'stackoverflow'))
// Output: 18 + 19 + 0 + 2 + 10 + 14 + 21 + 4 + 17 + 5 + 11 + 14 + 22 = 157
console.log(mapCharAndSum(15, 'stack overflow'))
// Crashes, because ' ' is not part of the alphabet and there is no error handling
I'm trying to write an app that will deliver combined results from multiple random selections. I am using 2 dimensional arrays. The first element of each secondary array is the number to 'roll' less than, to return the secondary array, which contains a string as its second element.
Further, inside the string is usually another function which calls another array.
All the returned strings are concatenated into a random phrase.
My expectation was that each time every function was called a new random result would be given. But what seems to be happening is once the first function call returns a result all nested function calls return the same result each time. What I would like is for each nested function call to return a new random result each time.
I hope I'm explaining this well enough. Here is some of the code I'm using with some 'sample' arrays to try to make clear what I'm doing.
// ROLL()
// times = NUMBER OF TIMES TO ROLL
// high = SIZE OF THE DIE / HIGHEST VALUE TO ROLL
// low = LOWEST VALUE (OPTIONAL)
// modifier = MODIFIER TO ROLL (OPTIONAL)
function roll(times, high, low, modifier) {
low = low || 1;
modifier = modifier || 0;
var result = 0;
for (var i = 0; i < times; i++) {
result += (Math.floor(Math.random() * ((high - low) + 1) + low));
}
result += modifier;
return result;
}
// RANDOMRESULT()
// array = A 2 DIM ARRAY
// modifier = MODIFIER TO ROLL (FOR THE ROLL() FUNCTION)
// dieSize = SIZE OF THE DIE (FOR THE ROLL() FUNCTION)
function randomResult(array, modifier, dieSize) {
var die = dieSize || array[array.length - 1][0];
var finalRoll = roll(1, die, 1, modifier);
for (i = 0; i <= array.length - 1; i++) {
if (finalRoll <= array[i][0]) {
return array[i];
}
}
}
//ASSUME MULTIPLE ARRAYS SET UP SIMILARLY
var array1 = [
[3, "You find " + roll(1, 10) + " dollars."],
[5, "You find " + roll(1, 20) + " dollars."],
[9, "You find " + roll(1, 30) + " dollars."]
];
var array2 = [...]
var someArray = [
[2, "Random result from array1. " + randomResult(array1)],
[4, "Random result from array2. " + randomResult(array2)],
[10, "Random result from array3. " + randomResult(array3)]
];
console.log(randomResult(someArray));
console.log(randomResult(someArray));
EDIT: The results are always random for each page refresh but when the randomResult() is called multiple times the same results occur from the nested array functions.
example of muliptle console.log returns...
(2) [2, "Random result from array1. 9,You find 1 dollars."]
(2) [10, "Random result from array3. 9,You find 2 dollars."]
(2) [10, "Random result from array3. 9,You find 2 dollars."]
(2) [2, "Random result from array1. 9,You find 1 dollars."]
(2) [10, "Random result from array3. 9,You find 2 dollars."]
(2) [4, "Random result from array2. 9,You find 2 dollars."]
So every time a '2' or less is rolled the roll() function from array1 always returns the same value. Same with the other results and the other arrays.
So my questions are first, why is this happening? Maybe because the first function call hasn't finished when the second is made?
Second are there any suggestions to fix this. Using object methods instead of 2 dim arrays maybe?
Any commentary or help is appreciated. Thanks.
When you call randomResult() multiple time, it refer back to the array1 and the value of array1 is already calculated when the script is loaded.
If you want a different value each time, put it inside a function and call the function to get the value.
function getRandomArray() {
return [
[3, "You find " + roll(1, 10) + " dollars."],
[5, "You find " + roll(1, 20) + " dollars."],
[9, "You find " + roll(1, 30) + " dollars."]
];
}
console.log(getRandomArray());
console.log(getRandomArray());
would like to ask about a JavaScript function.
I don't understand below function, I thought at line 4 fib(n-1) will return 1 and the latter fib(n-2) will return 0, and then they both add together as 1.
May I know why the final result for f(10); will be 55, can't get my head around this.
Anyone can help to explain to me what happening behind the scene, please?
Thanks! ;)
var f = function fib(n) {
if (n === 0) return 0;
if (n === 1) return 1;
if (n > 1) return fib(n - 1) + fib(n - 2); // *2
};
f(10); // 55
ref: https://slides.com/concise/js/fullscreen#/35
Like this. This is a typical recursive function, with two base cases and one recursive step.
Remember that if n is 10, then fib(n - 1) is fib(9), and so on:
fib(10) = fib(9) + fib(8) = 34 + 21 = 55
fib(9) = fib(8) + fib(7) = 21 + 13 = 34
fib(8) = fib(7) + fib(6) = 13 + 8 = 21
fib(7) = fib(6) + fib(5) = 8 + 5 = 13
fib(6) = fib(5) + fib(4) = 5 + 3 = 8
fib(5) = fib(4) + fib(3) = 3 + 2 = 5
fib(4) = fib(3) + fib(2) = 2 + 1 = 3
fib(3) = fib(2) + fib(1) = 1 + 1 = 2
fib(2) = fib(1) + fib(0) = 1 + 0 = 1
fib(1) = 1
fib(0) = 0
Side note: Although your example is a good illustration of recursive functions, it's an extremely inefficient way to calculate fibonacci numbers. A much better approach is to use memoization to eliminate the bulk of the inefficiency:
var fib = (function () {
var cache = [0, 1];
return function fib(num) {
if (!(num in cache)) {
cache[num] = fib(num - 1) + fib(num - 2);
}
return cache[num];
};
})();
console.log(fib(10));
http://jsperf.com/fibonacci-memoization-2015-04-01
this is called "recursive function" which one function calls itself.
basically there is no restriction (in terms of the OS) of doing so, a function basically gets interpreted/compiled to assembly code , and this assembly code can be copied and re-run with different (or the same) arguments.
I am taking an online JavaScript class and am stuck on a problem involving objects. In the following code, my assignment is to output a string that retrieves the name of each ranger (e.g. lighthouseRock.ranger1.name) and match their station to the corresponding item in the superBlinders array.
If I hard-code the ranger1 property, the output format is in the right ballpark. However, if I try to be creative and build a variable (thisRanger) to dynamically insert the appropriate ranger into my object, the routine returns an error "TypeError: Cannot read property 'name' of undefined". My thisRanger variable builds OK but whenever I try to insert it into my chain after lightHouseRock it causes the undefined problem. Here is my code:
var superBlinders = [ ["Firestorm", 4000], ["Solar Death Ray", 6000], ["Supernova", 12000] ];
var lighthouseRock = {
gateClosed: true,
weaponBulbs: superBlinders,
capacity: 30,
secretPassageTo: "Underwater Outpost",
numRangers: 0
};
function addRanger(location, name, skillz, station) {
location.numRangers++;
location["ranger" + location.numRangers] = {
name: name,
skillz: skillz,
station: station
};
}
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 3);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
var dontPanic = function () {
var message = "Avast, me hearties!\n";
message += "There be Pirates nearby! Stations!\n";
for (var i = 1; i <= lighthouseRock.numRangers; i++) {
var thisRangerNumber = i;
var thisRanger = "ranger" + thisRangerNumber;
// message += lighthouseRock.ranger1.name + ", man the " + superBlinders[lighthouseRock.ranger1.station][0] + "!\n";
message += lighthouseRock.thisRanger.name + ", man the " + superBlinders[lighthouseRock.thisRanger.station][0];
};
console.log(message);
}
The expected output should look something like this:
Avast, me hearties!
There be Pirates nearby! Stations!
<name>, man the <superblinder>!
<name>, man the <superblinder>!
<name>, man the <superblinder>!
How can I insert thisRanger into my code so that it gives me the expected output? Thank you very much for your help!
Working code!
It outputs all you want it todo!
UPDATE you have an error in your code I fixed that also..
Ranger2 will always be stationed on undefined since there aren't 3 stations when counting as an array, remember array in javascript starts counting from 0(zero). I changed Drew barontini to "0"
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 0);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
CODE OUTPUT
Avast, me hearties!
There be Pirates nearby! Stations!
Nick Walsh, man the Supernova,12000 Drew Barontini, man the Firestorm,4000Christine Wong, man the Solar Death Ray,6000
I didn't do much to change your code. But what I did is that I change your code into
message += lighthouseRock[thisRanger].name + ", man the " + superBlinders[lighthouseRock[thisRanger].station] +"\n";
Its important to know with javascript that you can use brackets [] to get to an object property if you build the stirng dynamicly.
var superBlinders = [ ["Firestorm", 4000], ["Solar Death Ray", 6000], ["Supernova", 12000] ];
var lighthouseRock = {
gateClosed: true,
weaponBulbs: superBlinders,
capacity: 30,
secretPassageTo: "Underwater Outpost",
numRangers: 0
};
function addRanger(location, name, skillz, station) {
location.numRangers++;
location["ranger" + location.numRangers] = {
name: name,
skillz: skillz,
station: station
};
}
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 0);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
var dontPanic = function () {
var message = "Avast, me hearties!\n";
message += "There be Pirates nearby! Stations!\n";
for (var i = 1; i <= lighthouseRock.numRangers; i++) {
var thisRangerNumber = i;
var thisRanger = "ranger" + thisRangerNumber;
// message += lighthouseRock.ranger1.name + ", man the " + superBlinders[lighthouseRock.ranger1.station][0] + "!\n";
message += lighthouseRock[thisRanger].name + ", man the " + superBlinders[lighthouseRock[thisRanger].station] +"\n";
};
console.log(message);
}
dontPanic();
I am getting -1 from myarray.indexOf(element) even when element appears to be in myarray.
Here's some code snippets:
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice(0,new_array.length);
var el, idx;
if (...) {
...
} else if ( old_array.length==new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx!=(-1) ) {
...
} else {
var a = "el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + nds.indexOf(el);
alert( a );
...
}
}
...
}
...
}
The alert shows me that nds does indeed contain el but the alert should only fire when idx==-1, which should only be true when nds does not contain el.
I know I haven't given enough information to determine the specific issue in my case, but maybe someone can tell me some general reasons which might cause this behavior?
Responses to a similar question suggested using jQuery inArray() instead of indexOf, but I want to know why indexOf doesn't work. Others suggested that indexOf is for strings, not arrays, but that's not true from the online docs I can find.
Use
nds.indexOf(parseInt(el,10))
where nds is an array and el is a number (or supposed to be a number)
Edit:
From msdn:
JavaScript is a loosely typed language, which means you do not declare
the data types of variables explicitly. In many cases JavaScript
performs conversions automatically when they are needed. For example,
if you add a number to an item that consists of text (a string), the
number is converted to text.
And I guess such conversion was the reason of indexOf returning -1 because one of your array contained number and other contained string.
For example:
old_array = ["10", "20", "30"];
new_array = [10, 20, 30];
Below is my attempt to answer your questions:
Why indexOf() does not work?
It does work and I guess it worked in your case too.
It returned -1 when el string, e.g "100", was not found in an array of numbers, e.g. nds=[100,200] which is true. Because "100" string is not same as 100 number.
Does indexOf() work with strings, array, etc?
Yes, indexOf() works with array (of number, string, or any object), as well as with string. But you have to make sure to check with same types.
What does parseInt() do?
To avoid unintended comparison of a number with a string, we can use parseInt(), for example parseInt("123", 10) returns the number 123.
The second argument 10 is called radix. A number (from 2 to 36) that represents the numeral system to be used.
Summary:
> "javascript is awesome".indexOf('v')
2
> [10, 20, 30].indexOf("20")
-1
> [10, 20, 30].indexOf(20)
1
> [10, 20, 30].indexOf( parseInt("20", 10) )
1
> typeof (100)
number
> typeof ("100")
string
> typeof( parseInt( "100", 10))
number
> parseInt( "100", 10)
100
> parseInt("100", 2)
4
> parseInt(11.3, 10)
11
> parseInt(11.3, 2)
3
> [10.3, 11.3, 12.3, 11].indexOf( parseInt(11.3, 10) )
3
To see all of above in action:
check the below code snippet but be aware of alert(); and console.log(); when you run it.
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice( 0, new_array.length ); // this seems to be redundant
var el, idx, msg;
if ( old_array.length == new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx != -1 ) {
msg = "Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
} else {
msg = "Not Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
}
console.log( msg );
alert( msg );
}
}
else {
var err = 'Array lengths are not same';
console.log( err );
alert( err );
}
}
// this will work
var old_array_g = [ 10, 20 ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// this will not work
var old_array_g = [ "10", "20" ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// Yes: indesOf works with strings too
var withStrings = "'javascript is awesome'.indexOf('v'): " + "javascript is awesome".indexOf('v');
console.log( withStrings );
alert( withStrings );
// parseInt() returns a number or say integer
var usingParse = "typeof(123): " + typeof( 123 ) + "; typeof( parseInt('123', 10) ): " + typeof ( parseInt('123', 10) ) + "; typeof ('123'): " + typeof('123');
console.log( usingParse );
alert( usingParse );
// parseInt() with base 2
var parseBase2 = "parseInt( '100', 2 ): " + parseInt('100', 2) + "; parseInt( '100' , 10): " + parseInt('100', 10);
console.log( parseBase2 );
alert( parseBase2 );
indexOf does work and does do what you say it does.
For example (to demonstrate from a console):
> a = [1,2,3,4,5,6,7,8];
[1, 2, 3, 4, 5, 6, 7, 8]
> b = a.slice(0,a.length);
[1, 2, 3, 4, 5, 6, 7, 8]
> b.indexOf(a[4])
4
If you're getting this error, it might mean you've mixed up source and destination (the array before the dot is the one being searched), or you have another subtle programming error (like you aren't comparing the array you think you're comparing).
When you use indexOf(value) on an Array, it returns you the index of the value in the array.
> var testArray = ["a","b","c"];
> testArray.indexOf(1)
-1
> testArray.indexOf("b")
1
> testArray.indexOf("c")
2
> testArray = [10,12,3];
> testArray.indexOf(12)
1
You should check what you get from el with a typeof(el)
Taking the top example:
where you have idx=nds.indexOf(el)
replace it with idx=nds.indexOf(''+el+'')
It solved a similar problem for me within the thing I'm working on, but I stumbled on it messing around looking for a solution.
Whether it's stable in all circumstances is something I can't answer.
If your search array contained numbers, and you want to search for items like 2 or "2"
nds = [1, 2, 3, 4, 5];
This works (Add plus)
nds.indexOf(+el)