Storing variables' names in an array - javascript

I have four variables and I want to change their values using a function where I just can put in an array storing the variables. I'm making a game which uses a coordinate system and therefore I have four coordinates that I want to constantly update with y-axis and x-axis. I have one array, yAxis, with all y values and one array, xAxis, with all x values. I want to combine them into the coordinates. Of course, I can update them using the following code:
yAxis = [10, 10, 9, 9];
xAxis = [4, 4, 5, 5];
coordinate1 = "" + yAxis[0] + xAxis[0];
coordinate2 = "" + yAxis[1] + xAxis[1];
coordinate3 = "" + yAxis[2] + xAxis[2];
coordinate4 = "" + yAxis[3] + xAxis[3];
But instead of changing their values like earlier I would like to do something like this: This function will take the array below, coordinatesArray as a, yAxis as b, and xAxis as c. Then x is just an integer.
test(a, b, c){
for(x = 0; x < 4; x++){
a[x] = "" + b[x] + c[x];
}
}
and then I would call this function like this:
coordinatesArray = [coordinate1, coordinate2, coordinate3, coordinate4];
test(coordinatesArray, yAxis, xAxis);
What it then should do with whatever array I run the test function with:
coordinatesArray[0] = "" + yAxis[0] + xAxis[0];
coordinatesArray[1] = "" + yAxis[1] + xAxis[1];
coordinatesArray[2] = "" + yAxis[2] + xAxis[2];
coordinatesArray[3] = "" + yAxis[3] + xAxis[3];
And for example coordinatesArray[0] should then represent coordinate1.
So I would create an array to store the variables so I can easily change which variable to target. The problem though, when I run this, a[x] isn't the variable name, instead, it is their values which means this doesn't work. So my question is, is there any way to store the variables' names in an array so I can target them using a function similar to the one I showed? I want to store the names of the variables in an array and then be able to use the name to target the variable so I can change their values.

Arrays in Javascript has only indices not names, that's why you need Object:
yAxis = [10, 10, 9, 9];
xAxis = [4, 4, 5, 5];
coordinatesArray = ['coordinate1', 'coordinate2', 'coordinate3', 'coordinate4'];
function test(a, b, c){
let arrOfObj = [];
for(let i=0; i < a.length; i++){
let obj = {};
obj[a[i]] = [b[i], c[i]];
arrOfObj.push(obj);
}
return arrOfObj;
}
console.log(test(coordinatesArray,yAxis,xAxis));

So this is what you're trying to do...
yAxis = [10, 10, 9, 9];
xAxis = [4, 4, 5, 5];
coordinate1 = "magic";
coordinate2 = "will";
coordinate3 = "happen";
coordinate4 = "here";
function test(a, b, c) {
for(x = 0; x < 4; x++){
window[a[x]] = "" + b[x] + c[x];
}
}
function log(a) {
let output = [];
for(x = 0; x < 4; x++){
output.push(window[a[x]]);
}
console.log(output);
};
coordinatesArray = ["coordinate1", "coordinate2", "coordinate3", "coordinate4"];
log(coordinatesArray);
test(coordinatesArray, xAxis, yAxis);
log(coordinatesArray);
...but the comments at your question are trying to say that you don't need the variables coordinate1, coordinate2 etc, you can just ALWAYS use one array, like this:
yAxis = [10, 10, 9, 9];
xAxis = [4, 4, 5, 5];
coordinatesArray = ["magic", "will", "happen", "here"];
function test(a, b, c) {
for(x = 0; x < 4; x++){
a[x] = "" + b[x] + c[x];
}
}
console.log(coordinatesArray);
test(coordinatesArray, xAxis, yAxis);
console.log(coordinatesArray);
right?

To me it looks like the OP asks for a simple object based key value store. But I might have gotten this wrong.
Thus the answer first puts the focus on how to generate a list of concatenated pairs of x-y coordinates, which in my opinion is the most pragmatic approach ...
const yAxis = [10, 10, 9, 9];
const xAxis = [4, 4, 5, 5];
const coordinatesList = yAxis.map((y, idx) => `${ y }${ xAxis[idx] }`);
console.log('(...coordinatesList) =>', coordinatesList);
.as-console-wrapper { max-height: 100%!important; top: 0; }
If one is not in need of assigning the list's coordinate values, each to a variable-name that could not already be generically created, this list already is a good enough storage.
On the other hand, a destructuring assignment of such a list allows the creation of tailored variables exactly within the scope that is needed (the example code of this approach does also refactor the mapping function from the first provided example) ...
function concatinateCorrespondingBoundArrayItem(partial, idx) {
return [partial, this[idx]].join('');
}
const yAxis = [10, 10, 9, 9];
const xAxis = [4, 4, 5, 5];
const [
foo,
bar,
baz,
biz
] = yAxis.map(concatinateCorrespondingBoundArrayItem, xAxis);
console.log('foo bar baz biz :', foo, bar, baz, biz);
.as-console-wrapper { max-height: 100%!important; top: 0; }
Finally, the storage the OP might have asked for, has to be object/map based. A possible approach could then look similar to this last provided example ...
function createCoordinateRecord(collector, coordinateName, idx) {
collector.storage[coordinateName] = [
collector.yCoordList[idx],
collector.xCoordList[idx]
].join('');
return collector;
}
const yAxis = [10, 10, 9, 9];
const xAxis = [4, 4, 5, 5];
const coordinateNameList = ['foo', 'bar', 'baz', 'biz']
const coordinatesMap = coordinateNameList.reduce(createCoordinateRecord, {
xCoordList: xAxis,
yCoordList: yAxis,
storage: {}
}).storage;
console.log('coordinatesMap :', coordinatesMap);
console.log('coordinatesMap.foo :', coordinatesMap.foo);
console.log('coordinatesMap.bar :', coordinatesMap.bar);
console.log('coordinatesMap[coordinateNameList[2]] :', coordinatesMap[coordinateNameList[2]]);
console.log('coordinatesMap[coordinateNameList[3]] :', coordinatesMap[coordinateNameList[3]]);
console.log('Object.keys(coordinatesMap) :', Object.keys(coordinatesMap));
console.log('Object.values(coordinatesMap) :', Object.values(coordinatesMap));
console.log('Object.entries(coordinatesMap) :', Object.entries(coordinatesMap));
.as-console-wrapper { max-height: 100%!important; top: 0; }

Related

How to add integer to 2-D array items

So lets say I have a log in google's console like this
[[296,279],[304,280],[308,280],[312,280]]
from my script here below
evtSource.onmessage = function(e) {
var obj = JSON.parse(e.data);
var line = JSON.stringify(obj.line)
var size = JSON.stringify(obj.lineWidth)
var color = JSON.stringify(obj.lineColor) // Not needed, but defined anyways.
var chat = JSON.stringify(obj.msg)
if (obj.ident === "") //mee
{
$.post("/draw.php?ing=_index", {
l: (line),
w : parseInt(obj.lineWidth) + 2,
c: ("ffffff"),
o: ("100"),
f: ("1"),
_: ("false")
})
console.log(line) //Logs the line. (Example in question.)
How could I add a value of 20 to each item in the array when it logs.
So it will log something like this
[[316,299],[324,300],[328,300],[332,300]]
and not like this (The original.)
[[296,279],[304,280],[308,280],[312,280]]
Use map:
const arr = [
[296, 279],
[304, 280],
[308, 280],
[312, 280]
];
const res = arr.map(e => e.map(f => f + 20));
console.log(res);
.as-console-wrapper {
max-height: 100% !important;
top: auto;
}
If you want to print the array with altered data but without altering the original you probably want to use JSON.stringify and JSON.parse to copy the array.
JSON.stringify also accepts a second parameter that allows you to edit the values while the object is being stringified.
var original = [
[296, 279],
[304, 280],
[308, 280],
[312, 280],
[[58, 60], [75, 84]],
4,
[[5, 9], [[0], [-3]], 8]
];
var json = JSON.stringify(original, function(key, value) {
return typeof value === "number" ? value + 20 : value;
});
console.log(json);
console.log(JSON.parse(json));
This will work, regardless of how many dimensions the array has (and is ES5 compatible).
You can use Array.map function.
Here we provide a function which will be executed with each element of the array. Which in your case will be another map function.
const line = [[296, 279],[304, 280],[308, 280],[312, 280]]
const out = line.map(arr => arr.map(x => x + 20))
console.log(out)

JavaScript : Rearrange array elements according to the absolute difference with x

Rearrange array elements according to the absolute difference with x i. e., the element having a minimum difference comes first and so on. Like I'm taking
array [10, 5, 3, 9, 2, 3] and x = 7 then the absolute difference for every element should be =
7 - 10 = 3(abs)
7 - 5 = 2
7 - 3 = 4
7 - 9 = 2(abs)
7 - 2 = 5
7 - 3 = 4
So according to the difference with X, elements are arranged as [5,9,10,3,3,2].
I have tried this by the code below but still failing to do so:
function ar(a, x) {
var obj = {}, d, i, res;
for (i = 0; i < a.length; i++) {
d = Math.abs(a[i] - x);
obj[a[i]] = d;
}
res = Object.keys(obj).sort(function(a, b) {
return obj[a] - obj[b]
});
for (i = 0; i < res.length; i++) {
res[i] = parseInt(res[i]);
}
return res;
}
var o = ar([10, 5, 3, 9, 2, 3], 7);
console.log(o);
as you can see I'm making object which have only one key but values repeat here .. I can't find another way of solving it the answer I get is [5,9,10,3,2]:(..
as you can see I'm making object which have only one key but values
repeat here
Objects can't have duplicate properties, so when you repeat a property it overrides the previous one with new value
You can simply use sort with Math.abs
let arr = [10, 5, 3, 9, 2, 3]
let x = 7
let sortByDiff = (arr,x) => arr.sort((a,b)=> Math.abs(a-x) - Math.abs(b-x))
console.log(sortByDiff(arr,x))
Just define your distance function:
const dist = x => Math.abs(x - 7);
and pass the difference of it applied to both argument of the sort method.
arr.sort((a, b) => dist(a) - dist(b));
See MDN for more info on the sort method.
const arr = [10, 5, 3, 9, 2, 3];
const dist = x => Math.abs(x - 7);
const sorted = arr.sort((a, b) => dist(a) - dist(b));
console.log(sorted);

Javascript dynamic nested object

My goal is to generate serialized objects in the main object.
A solar system is my idea of nesting where I can access a variable by calling it like
universe.system1.planet4.x
universe > system > planet > etc
Im stuck on generating anything thats nested. So far I can only get 1 level of nesting to work correctly.
setInterval(onTimerTick, 1000);
function onTimerTick() {
var entityCount=4;
for (i=1; i<entityCount;i++){
console.log('system' + i)
universe['planet'+i]=[entityCount,entityCount,entityCount,entityCount];
}//entitycounts in object are placeholder for more data
console.log(universe);
}
var universe = {
}
Output
Object {
system0: [5, 5, 5, 5],
system1: [5, 5, 5, 5],
system2: [5, 5, 5, 5],
system3: [5, 5, 5, 5]
}
Anytime I try to add any nesting it won't generate.
Is this something like this?
You would have to create X nested loops, with X being the number of nested levels you want to create.
const nbSystem = 5;
const nbPlanetPerSystem = 3;
// Create the base
const universe = {};
// Generate systems
for (let i = 0; i < nbSystem; i += 1) {
universe[`system${i + 1}`] = {};
// Generate planets
for (let j = 0; j < nbPlanetPerSystem; j += 1) {
universe[`system${i + 1}`][`planet${j + 1}`] = 'something';
}
}
console.log(universe);
console.log(universe.system3.planet3);

reversing an array in javascript

I have a Javascript function called reverseArray that takes an array as the argument and returns a new array which has the same values as the input array in reverse order. I want to create a function called reverseArryInPlace which would change the value of the input array to the reverse order.
function reverseArray(inputArray) {
var outputArray = [];
for (var i = inputArray.length - 1; i >= 0; i--)
outputArray.push(inputArray[i]);
return outputArray;
}
function reverseArrayInPlace(inPlaceInputArray) {
inPlaceInputArray = reverseArray(inPlaceInputArray);
console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
return inPlaceInputArray;
}
var arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]
Here is the result I get when I execute this chunk of code:
Inside reverseArrayInPlace: 5,4,3,2,1
Outside reverseArrayInPlace: 1,2,3,4,5
Within the reverseArrayInPlace function the arrayValue variable has been reversed as expected. Why is it that when I reference the same variable outside the reverseArrayInPlace function, it is back to the original order?
If you want to reverse it in place, you have to reverse it in place.
function reverseArrayInPlace(array) {
for (let i = 0, j = array.length - 1; i < j; i++, j--)
[array[i], array[j]] = [array[j], array[i]];
}
const a = [1,2,3,4,5];
reverseArrayInPlace(a);
console.log(a);
The underlying problem here is that primitives are passed by value in JavaScript. See the following question for details:
Javascript by reference vs. by value
As a simple example, here is a function that attempts to mutate a string that was passed to it:
var outsideValue = 'foo'
function mutate(value) {
value = 'fish'
}
mutate(outsideValue);
console.log(outsideValue);
However, the console output is foo.
This happens because the value variable within the mutate function is a variable that has a reference to outsideValue when the function is initially invoked. When it is assigned the new value within the function body, it merely changes the value variable to reference a new string. As a result, the outsideValue is untouched.
Check this answer for an example that reverses in place:
https://stackoverflow.com/a/43486686/249933
Notice, that it does not re-assign the function argument.
As others have said, arrays are objects so they're passed by reference. You have to modify the original array, not create a new one.
So here's another version of reverseInPlace, it uses shift to remove the last element from the array and splice to insert it in the new location:
function reverseInPlace(arr) {
var i = arr.length;
while (i--) {
arr.splice(i, 0, arr.shift());
}
}
var arr = [1,2,3,4,5];
console.log('Before: ' + arr.join());
reverseInPlace(arr);
console.log('After: ' + arr.join());
For some fun, you can also leverage sort:
NB: this only works in some browsers, it's dependent on the built-in sort algorithm which is implementation dependent.
function reverseInPlace(arr) {
arr.sort(() => 1);
}
var arr = [47, 95, 80, 62, 8, 34, 31, 17, 62, 17, 85, 72, 51, 20, 68, 60, 30, 84, 7, 34];
console.log('Before: ' + arr.join());
reverseInPlace(arr);
console.log('After : ' + arr.join());
function reverseArray(inputArray) {
var outputArray = [];
for (var i = inputArray.length - 1; i >= 0; i--)
outputArray.push(inputArray[i]);
return outputArray;
}
function reverseArrayInPlace(inPlaceInputArray) {
inPlaceInputArray = reverseArray(inPlaceInputArray);
console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
return inPlaceInputArray;
}
var arrayValue = [1, 2, 3, 4, 5];
**arrayValue = reverseArrayInPlace(arrayValue);**
alert('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]
//
your code is correct your just need to replace one line and write
arrayValue = reverseArrayInPlace(arrayValue);
instead of
reverseArrayInPlace(arrayValue);
Then arratValue will print expected values

Convert an array into cumulative% array

I have an array like this one:
[30, 10, 4, 3, 3]
And I need to transform this to a cumulative% array in such a way that each value is the sum of all values upto there divided by sum of all values in the array.
In this case, the total is 50. So, the first value will be 30/50, i.e., 0.6 or 60%. The 2nd value will be (30+10)/50, i.e., 0.8 or 80% and so on.
The final array in this will be:
[60%, 80%, 88%, 94%, 100%]
How can I do this transformation with JavaScript? What would be the most efficient way to do so?
Try,
var x = [30, 10, 4, 3, 3];
var y = x.reduce(function(a,b){ return a+b; }, 0)
x = x.map(function(itm, index){
for(var i=0;i<index;i++) itm += x[i];
return (itm/y * 100);
});
x; //[60, 80, 88, 94, 100]
And this will look more elegant,
var x = [30, 10, 4, 3, 3];
var y = x.reduce(function(a,b){ return a+b; }, 0), sum = 0;
x = x.map(function(itm) { return sum += itm, (sum / y) * 100; });
Try
let nums = [30, 10, 4, 3, 3];
let sum = nums.reduce((prev,curr) => prev + curr);
let result = nums.map((num,i) => Math.round(nums.slice(0,i + 1).reduce((prev,curr) => prev + curr) / sum * 100) + '%');
You first need to compute the sum to get the denominator (50).
Then you need to apply the treatment for each element (new_value=value/denominator)
To do so you can use simple for loops, or even cleaner with arrays specific functions, to avoid any error:
var array = [30, 10, 4, 3, 3];
// Compute the denominator
var sum = array.reduce(function(pv, cv) { return pv + cv; }, 0);
// Duplicate the array
var arrayResult = array;
// Apply the function to each given "myArray[ind]" element
arrayResult.forEach( function(cv,ind,myArray) {
myArray[ind] = cv/sum;
// Add the previous accumulator if any
if( ind>0 ) {myArray[ind] += myArray[ind-1];}
} );
See it running on JSFiddle
edited to add the accumulator
Combine two maps, one to create an array with cumulative sums, the second to divide by the sum.
function cumulative_ratio(array) {
var x = 0;
return array .
map(v => x += v) .
map(v => v / x);
}

Categories

Resources