Dynamic Concatenation in Javascript Array - javascript

Let's say I have an array of data and a variable (or multiple variables)
var i = 1;
var arr = {
1: ['whatever' + i,'there are ' + i + ' dogs in the yard.', etc],
}
Is there a way to dynamically update the variable(s) in the array later on in a function?
So
function start() {
i++;
alert(arr[1][0]);
}
Would output "whatever2" instead of "whatever1"

You could have an array and push() stuff you need, but when the string is made, it won't change anymore.
var array = ['whatever',i,'there are ',i,' dogs in the yard.'];
array.push('more stuff');
array.push('even more stuff');
var string = array.join('')
//string = 'whatever[whatever "i" is during join]there are[whatever "i" is during join]dogs in the yard.more stuffeven more stuff'

You could use functions instead:
var i = 1;
var arr = {
1: [
function() { return 'whatever' + i },
function() { return 'there are ' + i + ' dogs in the yard.' },
function() { return 'etc' }
],
}:
Which would change your calls to:
function start() {
i++;
alert(arr[1][0]());
}

Try this code:
var arr = function(i){
return {
1: ['whatever' + i,'there are ' + i + ' dogs in the yard.', etc],
}
}
var anyNumber = 1;
var updatedVar = arr(anyNumber);

Related

how to return this value from my function? is it wrong method?

I don't understand how to solve the following problem when return the value from nested function. is it wrong method. How can I get it?
My basic purpose is to get array values (all coordinates) from var mymap_coordinates, but it can't. that's why I use .toString() to test.
*<script>
mymap.on( //leftlet code
'contextmenu',
function (event)
{
var tg_marker = L.marker(event.latlng, {icon: treegroupIcon}).addTo(mymap);
store_coordinates[incre_coord] = new Point(tg_marker.getLatLng().lat.toFixed(8), tg_marker.getLatLng().lng.toFixed(8));
var n = store_coordinates.length;
var mymap_coordinates = abcdefg(store_coordinates, n);
window.alert (mymap_coordinates.toString()); //This alert can't print all array value when return the value from abcdefg function
incre_coord = incre_coord + 1;
}
);
function abcdefg(points, n)
{
.......
.......
.......
// return Result
var num = 0;
var map_coordinate = new Array();
for (let temp of abc.values())
{
map_coordinate[num] = "[" + temp.x + ", " + temp.y + "]";
num = num + 1;
}
window.alert (map_coordinate.toString()); //This alert can print all array value
return map_coordinate;
}
</script>*

Count duplicate property values of a nested Javascript object

I'm feeding in information in from an API with the format -
Records = { 0: {fields: {name: "nameExample" place: "placeExample"} }
{1: {fields: {name: "nameExample" place: "placeExample"} }
etc etc
I'm looking for a way to count duplicates of the 'place' field in the format: Scotland(4), London(6) etc. where the number is the amount of times it repeats.
The closest I've got as of yet is counting the letters in each place name, but I'm not sure what I'm doing wrong. I think if I can get them in the same array then it would be simple, but when I tried to do that it put each place in a different array.
Also must be vanilla javaScript, no jQuery. Many thanks!
var URL = new Array();
URL[0] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45";
URL[1] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=45";
URL[2] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=90";
var nRequest = new Array();
for (var i=0; i<3; i++){
(function(i) {
nRequest[i] = new XMLHttpRequest();
nRequest[i].open("GET", URL[i], true);
nRequest[i].onreadystatechange = function (oEvent) {
if (nRequest[i].readyState === 4) {
if (nRequest[i].status === 200) {
var data = JSON.parse(nRequest[i].responseText);
var url = 'http://media.vam.ac.uk/media/thira/collection_images/';
for (let key in data.records) {
let value = data.records[key];
let image = value.fields.primary_image_id;
let res = image.substr(0, 6);
document.querySelector(".map").innerHTML += '<div class="' + value.fields.place + ' map"> ' + value.fields.place + ' <br> </div>';
}
} else {
console.log("Error", nRequest[i].statusText);
}
}
//
};
nRequest[i].send(null);
})(i);
};
If thats the data structure you can solve it like so:
const Records = [
{fields: {name: "nameExample", place: "placeExample"}},
{fields: {name: "nameExample", place: "placeExample"}}
];
const result = Records.reduce((acc, {fields}) => {
if(acc[fields.place]) acc[fields.place]++;
else acc[fields.place] = 1;
return acc;
}, {})
console.log(result);
You can use the reduce function to convert the array data.records to an object with the place as key and number of occurrences as value.
data.records.reduce((accum, currVal) => {
if (!(currVal.fields.place in accum)){
accum[currVal.fields.place] = 0;
}
accum[currVal.fields.place] += 1;
return accum;
}, {});

How to return multiple values ​with a function?

In what way could I make the function return 3 values ​​to me so that those 3 values ​​would serve as input parameters for another function (as if it were a callback --which in fact, I think it is--)?
Until now, try the following (although it did not work):
var resultado;
function num_2(repet){
for (var i = 0; i > repet-1; i++) {
if (i>=1) {
return i + ", ";
}else{
return i;
}
}
}
function sumarr(a,b,c){
if (a!="" && a!=null) {
resultado = a+b+c;
return "\n" + "resul: " + resultado + '\n' + "1: " +
a + '\n' + "2: " + b + '\n' + "3: " + c + '\n' + '\n';
}else{
return "noting";
}
}
console.log("\n" + "callback 2: " + sumarr(num_2(3)));
You can return an array from the first function and pass each element to another other function as independent argument using Spread Operator.
var resultado;
function num_2(repet){
return [...Array(repet)].map((x,i) => i)
}
function sumarr(a,b,c){
return a + b + c
}
console.log("\n" + "callback 2: " + sumarr(...num_2(3)))
If its hard for you to understand the first function so its same as
function num_2(repet){
let res = [];
for(let i = 0;i<repet;i++){
res.push(i)
}
return res;
}
You have two options; return a JSON object, return an array.
Returning a JSON object you can name the properties then modify the second function to accept the object and access the properties;
var input = function() {
return {
a: 1,
b: 2
};
}
var output = function(obj) {
console.log(obj.a);
console.log(obj.b);
}
output(input());
Returning an array and using that as the arguments to call the function with apply() or with spread syntax
var input = function() {
return [1, 2];
}
var output = function(a, b) {
console.log(a);
console.log(b);
}
output.apply(this, input());
output(...input());
These all have the same result printing the following in the console;
1
2
with JS object :
var Vals = Return3Values();
console.log( Vals.a, Vals.b, Vals.c );
function Return3Values()
{
return {a:5, b:'hello', c:15 }
}
If you are able to use the latest JS features, you can use Destructuring Assignment in your functions to solve this and clean up your code.
function logLotsOfThings({thing1, thing2, thing3}) {
console.log(thing1, thing2, thing3)
}
function getLotsOfThings() {
return {
thing1: "I am thing 1",
thing2: "I am thing 2",
thing3: "I am thing 3"
}
}
logLotsOfThings(getLotsOfThings())

JSON return value to global variable

Simply my code looks like this:
var thevariable = 0;
For(){
//somecode using thevariable
$.getJSON('',{},function(e){
//success and i want to set the returned value from php to my variable to use it in the forloop
thevariable = e.result;
});
}
my main problem that the variable value stays "0", during the whole For loop, while i only want it to be "0" at the first loop, then it takes the result returned from PHP to use it on for loop.
here it my real code if you need to take a look:
var orderinvoice = 0;
for(var i=0; i<table.rows.length; i++){
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g,'')).replace(/Qty /g,'');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g,'');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', {'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink}, function(e) {
console.log();
document.getElementById("result").innerText= document.getElementById("result").innerText + "Order #"+e.result+" Created Successfully ";
document.getElementById("invoker").innerText = ""+e.invoice;
orderinvoice = e.invoice;
if(i+1 == table.rows.length){
document.getElementById("result").innerText= document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
});
in a loop block, before one ajax complete other one will be run and this's javascript natural treatment. For your case you can call a function at the end of success event. Do something like this:
var i = 0;
doSt();
function doSt() {
var orderinvoice = 0;
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g, '')).replace(/Qty /g, '');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g, '');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', { 'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink }, function(e) {
console.log();
document.getElementById("result").innerText = document.getElementById("result").innerText + "Order #" + e.result + " Created Successfully ";
document.getElementById("invoker").innerText = "" + e.invoice;
orderinvoice = e.invoice;
if (i + 1 == table.rows.length) {
document.getElementById("result").innerText = document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
i++;
if (i < table.rows.length) doSt();
});
}
I think you need a recursive function that always deals with the first element in your rows array and then splices it off and calls itself. For example, something like this:
function getStuff(rows, results) {
if (rows.length > 0) {
var ordername = rows[0].cells[5].innerText;
$.getJSON('orderprocess.php', { 'ord_name': ordername }, function (e) {
// do some stuff
results.push('aggregate some things here?');
rows.splice(0, 1);
return getStuff(rows, results);
});
} else {
return results;
}
}
When the array is spent, results will be returned with whatever aggregate you wanted at the end of the cycle. Then, you can do as you please with the results. I think you can also manipulate the DOM inside the function as you see fit if that makes more sense. Hope this helps.

How to add the numeric values of properties of a nested array?

I'm trying to figure out how to make a function that adds the values of the elements chosen by the user and be able to display the results via prompt and console.log. Also, I'm wondering if there is a way to do it in which I don't need to specify the elements selected in order for the function to find within the code which elements were selected and execute the addition function. Because obviously if the list of options were longer I wouldn't want to have to make a new function for each potential combination of selections. As a side note, I guess the same problem would apply to the if statements, would switch statements be the most efficient way to tackle needs for "DRY" code in that instance?
My javascript code: Please assume that the user selects only the first elements of the nested arrays. Also, that term "one" is worth $8.
var selection = new Array (3);
selection[0] = new Array ('$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8');
selection[1] = new Array ('phone1', 'phone2', 'phone3');
selection[2] = new Array ('one', 'two', 'three');
function pickPhone () {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3");
if (yourPhone == selection[1][0]) {
console.log(selection[1][0] + " will cost: " + selection[0][0]);
alert(selection[1][0] + " will cost: " + selection[0][0]);
pickTerm ();
} if (yourPhone == "phone2") {
alert(selection[1][1] + " will cost: " + selection[0][1]);
} if (yourPhone == "phone3") {
alert(selection[1][2] + " will cost: " + selection[0][2]);
}
}
function pickTerm () {
var yourTerm = prompt("pick term: one, two or three?");
if (yourTerm == selection[2][0]) {
alert("Your total so far is: ??");
}
}
pickPhone ();
Any help is greatly appreciated, thank you.
A solution that keeps your arrays
http://jsfiddle.net/OxyDesign/o10ezyun/
JS
var selection = new Array(3);
selection[0] = new Array(1,2,3,4,5,6,7,8);
selection[1] = new Array('phone1', 'phone2', 'phone3');
selection[2] = new Array('one', 'two', 'three');
var firstValue;
function pickPhone() {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3"),
index = selection[1].indexOf(yourPhone);
if(!~index){
pickPhone();
}else{
firstValue = selection[0][index];
alert(selection[1][index] + " will cost: $" + firstValue);
pickTerm();
}
}
function pickTerm() {
var yourTerm = prompt("pick term: one, two or three?"),
index = selection[2].indexOf(yourTerm),
finalValue = '$'+(firstValue+selection[0][index]);
if(!~index){
pickTerm();
}else{
alert("Your total so far is: "+finalValue);
}
}
pickPhone();
I'am not sure what problem you are actually solving.
How long these lists are (phones, costs, etc)?
What type of mapping is set for those items?
For now I'd recommend to merge corresponding values in objects like this:
// item -> cost
var phones = [
{title: 'phone1', cost: '$1'},
{title: 'phone2', cost: '$2'},
{title: 'phone3', cost: '$3'}
],
terms = [
{title: 'one', cost: '$8'},
{title: 'two', cost: '$2'},
{title: 'three', cost: '$3'}
],
phonesListWithCosts = (function(list) {
return list.reduce(function(memo, item) {
return memo + item.title + ': ' + item.cost;
}, '');
}(phones)),
termsList = (function(list) {
return list.reduce(function(memo, item) {
return memo + ', ' + item.title;
}, '');
}(terms)),
findBy = function(array, property, value) {
return array.filter(function(item) {
return item[property] === value;
})[0];
},
getItem = function(list, promptMessage) {
var selectedItemTitle = prompt(promptMessage);
return findBy(list, 'title', selectedItemTitle);
},
getItemCost = function(item) {
return parseInt(item.cost.replace(/\D/g, ''), 10);
},
pickPhone = function() {
var selectedPhone = getItem(phones, 'pick phone: ' + phonesListWithCosts),
firstPhone = phones[0],
message;
if (selectedPhone) {
message = [selectedPhone.title, 'will cost:', selectedPhone.cost].join(' ');
console.log(message);
alert(message);
if (selectedPhone === firstPhone) {
pickTerm(getItemCost(selectedPhone));
}
}
},
pickTerm = function(accumCost) {
var selectedTerm = getItem(terms, 'pick term: ' + termsList),
totalCost,
message;
if (selectedTerm) {
totalCost = accumCost + getItemCost(selectedTerm);
message = 'Your total so far is: $' + totalCost;
alert(message);
}
};
pickPhone();
jsbin demo.

Categories

Resources