Generate collision objects from multidimensional array for HTML5 tile map - javascript

I am creating an HTML5 platform game using objects for collision detection and using a 2d tile map to render the level. That is all working.
I want to use the same 2d array to build the object array dynamically to allow the player to build maps as required and also for ease of creating the maps in the first place. When hardcoding the object array, everything works so I know that the collision detect and game engine work.
While I can create objects for each individual array element, I am looking to build objects that have width based on the number of matching elements in the array, (each element is 25x25) i.e. if 3 array elements are 1,1,1 then the object will have a width of 75. Maybe some code will help explain:
The following tile array
var arr1 = [
[0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,2,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0,0,0]
];
should produce the following object array:
[
{x: 75, y: 0, width: 100, height: 25, value: 1},
{x: 75, y: 50, width: 50, height: 25, value: 2},
{x: 0, y: 100, width: 75, height: 25, value: 3}
]
but it instead it is producing the following:
[
{x: 75, y: 0, width: 25, height: 25, value: 1},
{x: 100, y: 0, width: 25, height: 25, value: 1},
{x: 125, y: 0, width: 25, height: 25, value: 1}
]
My logic is obviously wrong but I can't for the life of me get it.
Example code is below:
Any help really appreciated:
var tmpObj = {};
var objArr = [];
var arr1 = [
[0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,2,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0,0,0]
];
for (let i=0; i<arr1.length; i++) {
for (let j=0; j<arr1[i].length; j++) {
if (arr1[i][j] > 0 && arr1[i][j] < 6) { // platform blocks only 1 - 5
if (tmpObj.x === undefined) {
tmpObj = {
x: j * 25,
y: i * 25,
width: 25,
height: 25,
value: arr1[i][j]
}
} else if (arr1[i][j] == arr1[i][j-1] && arr1[i][j] == tmpObj.v) {
tmpObj.w += 25;
} else if (arr1[i][j] !== tmpObj.v) { // new tile type
objArr.push(tmpObj);
tmpObj = {
x: j * 25,
y: i * 25,
width: 25,
height: 25,
value: arr1[i][j]
}
} else {
objArr.push(tmpObj);
tmpObj = {};
}
}
}
}
console.log(objArr);

Looking at what you are trying to do your implementation is way too complicated. Rather than hunt down the bug (for which I would have used devTools and stepped through the code line by line to find where the problem was.) I rewrote the function using a while loop to find the width of joined tiles.
I took liberty with the object property names but I am sure you can change it to your needs.
const objArr = [];
const arr1 = [
[0,0,0,1,1,1,1,0,1,0],
[2,0,0,0,0,0,0,0,0,3],
[0,0,0,4,4,0,4,4,4,4],
[0,0,0,0,0,0,0,0,0,0],
[3,3,3,5,5,4,0,0,0,0]
];
const tileSize = 25;
for (let i = 0; i < arr1.length; i++) {
const row = arr1[i]
for (let j = 0; j < row.length; j++) {
if (row[j] > 0 && row[j] < 6) {
let count = j + 1;
while (count < row.length && row[count] === row[j]) { count += 1 }
objArr.push({
x: j * tileSize,
y: i * tileSize,
w: tileSize * (count - j),
h: tileSize,
tile: row[j]
});
j = count - 1;
}
}
}
// show results
objArr.forEach(log);
// unrelated to answer. (I hate the console SO has for snippets.)
function log(data){
show.appendChild(
Object.assign(
document.createElement("div"), {
textContent :
Object.keys(data).reduce((str, key) => {
return str + (" " + key+ ": " + data[key]).padEnd(8,".");
}, ""
)
}
)
);
}
<code id="show"></code>

Related

How to reverse the averaging of multiple vectors in JavaScript?

In the code below I mix various flavors of icecream together (chocolate, strawberry, vanilla, & neapolitan) in order to produce a new, never-before-seen flavor of icecream.*
A flavor is represented by an array where the first element is simply a string, the name of the flavor.
The second element is a number from 0 to 100 representing the vanilla component, the third the chocolate component, and the fourth the strawberry component.
Mixing is performed by averaging all the input flavors (arrays) together.
After mixing, I attempt to determine which flavor the new mixture is most similar to. This is done by taking the sum of the absolute difference of the mystery icecream and known flavors. The smaller the sum, the smaller the difference and greater the similarity.
In this specific example, the mixture is 6 parts strawberry icream and 1 part of each of the other flavors. Predictably, the strawberry is calculated to be the most similar, followed by neapolitan, because it is itself a mixture.
This is a good ways towards reverse-engineering the mixture, but I want to go further. I want to determine the precise proportions of each flavor that went into the mixture.
In this example it would be as stated above: 6 strawberry, 1 vanilla, 1 chocolate, 1 neapolitan.
Of course, there may be many (infinite?) ways to come up with a given mixture. But I am looking for the most parsimonious possibility.
For example, 1 part neopolitan plus 1 part strawberry is identical to 4 parts strawberry plus 3 parts of every other flavor. But the former is more parsimonious.
How would I go about predicting how a mixture was created?
I don't know what the technical term for this is.
const mixture = mixIcecreams([
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['neapolitan', 33, 33, 33],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
]);
console.log(mixture);
const distances = calculateDistances(mixture, [
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['strawberry', 0, 0, 100],
['neapolitan', 33, 33, 33],
]);
console.log('Distances:');
console.log(distances);
console.log(
`The icecream named "${mixture[0]}" is most similar to "${distances[0][0]}" icecream.`
);
// Calculate the "distance" between a "target" vector and "sources" vectors.
// Smaller distance means more similarity.
function calculateDistances(target, sources) {
return (
sources
.map((source) => [
// First element is the label.
source[0],
target.reduce(
(distance, value, i) =>
// Avoid doing math with the first element (the label).
i === 0 ? distance : distance + Math.abs(source[i] - value),
0
),
])
// Sort by shortest distance (most similar).
.sort((a, b) => a[1] - b[1])
);
}
function mixIcecreams(icecreams) {
return icecreams.reduce(
(mixture, icecream, i) => {
icecream.forEach((value, j) => j !== 0 && (mixture[j] += value));
if (i === icecreams.length - 1) {
return mixture.map((value, j) =>
// Ignore the first element, it's just a label.
j === 0 ? value : value / icecreams.length
);
}
return mixture;
},
Array.from({ length: icecreams[0].length }, (_, i) =>
i === 0 ? 'mixture' : 0
)
);
}
*Patent pending.
If I understand your problem correctly, in mathematical terms you seem to need the solution of an underdetermined system of equations, in the least squares sense.
I put up a quick solution that can be improved upon.
I can further explain, if interesting.
Edit: I added a simple integer approximation, to find an integer solution that best approximates the percentual one.
const mixture = mixIcecreams([
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['neapolitan', 33, 33, 33],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
['strawberry', 0, 0, 100],
]);
console.log(mixture);
const distances = calculateDistances(mixture, [
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['strawberry', 0, 0, 100],
['neapolitan', 33, 33, 33],
]);
console.log('Distances:');
console.log(distances);
console.log(
`The icecream named "${mixture[0]}" is most similar to "${distances[0][0]}" icecream.`
);
const probableMixture = mostProbableMixture(mixture, [
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['strawberry', 0, 0, 100],
['neapolitan', 33, 33, 33],
]
);
console.log('most likely mixture, percent', probableMixture)
const im = integerMix(probableMixture, 100);
// the second argument, nMax, is the maximum number allowed from one basic flavor
// the larger nMax, the closer you may get to the exact mixture
console.log('integer mixture', im)
const rm = repeatIntegerMix(im, [
['vanilla', 100, 0, 0],
['chocolate', 0, 100, 0],
['strawberry', 0, 0, 100],
['neapolitan', 33, 33, 33],
]);
console.log('verify mixture', mixIcecreams(rm))
// Calculate the "distance" between a "target" vector and "sources" vectors.
// Smaller distance means more similarity.
function calculateDistances(target, sources) {
return (
sources
.map((source) => [
// First element is the label.
source[0],
target.reduce(
(distance, value, i) =>
// Avoid doing math with the first element (the label).
i === 0 ? distance : distance + Math.abs(source[i] - value),
0
),
])
// Sort by shortest distance (most similar).
.sort((a, b) => a[1] - b[1])
);
}
function mixIcecreams(icecreams) {
return icecreams.reduce(
(mixture, icecream, i) => {
icecream.forEach((value, j) => j !== 0 && (mixture[j] += value));
if (i === icecreams.length - 1) {
return mixture.map((value, j) =>
// Ignore the first element, it's just a label.
j === 0 ? value : value / icecreams.length
);
}
return mixture;
},
Array.from({ length: icecreams[0].length }, (_, i) =>
i === 0 ? 'mixture' : 0
)
);
}
function mostProbableMixture(mixture, baseFlavors){
const nVars = baseFlavors.length,
nEq = mixture.length - 1,
At = baseFlavors.map(flavor=>flavor.slice(1)),
b = mixture.slice(1),
AAt = Array(nEq).fill(0).map(z=>Array(nEq));
//compute A*At
for(let i = 0; i < nEq; i++){
for(let j = 0; j < nEq; j++){
AAt[i][j] = 0;
for(let k = 0; k < nVars; k++){
AAt[i][j] += At[k][i]*At[k][j];
}
}
}
// normalize rows
for(let i = 0; i < nEq; i++){
let maxRow = Math.abs(b[i]);
for(let j = 0; j < nEq; j++){
maxRow = Math.max(maxRow, Math.abs(AAt[i][j]));
}
for(let j = 0; j < nEq; j++){
AAt[i][j] = AAt[i][j] /maxRow;
}
b[i] = b[i]/maxRow;
}
// Solve (for t) A * At * t = b
// Gaussian elimination; diagonal dominance, no pivoting
for(let j = 0; j < nEq-1; j++){
for(let i = j+1; i < nEq; i++){
let f = AAt[i][j] / AAt[j][j];
for(let k = j+1; k < nEq; k++){
AAt[i][k] -= f * AAt[j][k];
}
b[i] -= f*b[j];
}
}
const t = Array(nEq).fill(0);
t[nEq-1] = b[nEq-1]/AAt[nEq-1][nEq-1];
for(let i = nEq-2; i >= 0; i--){
let s = b[i];
for(let j = i + 1; j<nEq; j++){
s -= AAt[i][j]*t[j];
}
t[i] = s/AAt[i][i];
}
// the solution is y = At * t
const y = Array(nVars).fill(0);
let sy = 0;
for(let i = 0; i < nVars; i++){
for(let j = 0; j < nEq; j++){
y[i] += At[i][j] * t[j];
}
sy += y[i];
}
for(let i = 0; i < nVars; i++){
y[i] = y[i]/sy*100;
}
return y.map((yi, i)=>[baseFlavors[i][0], yi]);
}
function integerMix(floatMix, nMax){
const y = floatMix.map(a=>a[1]),
maxY = y.reduce((m,v)=>Math.max(m,v));
let minAlpha = 0, minD = 1e6;
for(let alpha = 1/maxY; alpha <= nMax/maxY; alpha+=(nMax-1)/10000/maxY){
//needs refining!!
const sdif = y.map(v=>Math.pow(Math.round(v*alpha)-v*alpha, 2));
const d2 = sdif.reduce((s,x)=>s+x);
if(d2 < minD){
minD = d2;
minAlpha = alpha;
}
}
return floatMix.map(([name, f]) => [name, Math.round(minAlpha*f)]);
}
function repeatIntegerMix(integerMix, baseFlavors){
return integerMix.flatMap(([name, n], i)=> Array.from({length: n}, e=>baseFlavors[i].slice(0)));
}

How can I return only the number of matching pair values in array?

Say I found a box of loose shoes (all the same kind) at a garage sale, and I've created an array with each individual shoe listed by shoe size.
I want to display the number of paired values of shoe sizes in the array. For example, I have this array:
[10,10,10,10,20,20,20,30,50]
I would like to display 3 because we have 3 pairs of numbers:
10,10
10,10
20,20
And 3 remaining values that don't have a matching pair-value (20,30,50).
How can I do this?
function pairNumber(arr) {
var sorted_arr = arr.sort();
var i;
var results = [];
for (i = 0; i < sorted_arr.length; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
return results.length;
}
console.log(pairNumber([10, 10, 10, 10, 20, 20, 20, 30, 50]))
Here is another approach using a Set:
function pairNumbers(arr) {
let count = 0;
const set = new Set();
for (let i = 0; i < arr.length; i++) {
if (set.delete(arr[i])) {
count++;
} else {
set.add(arr[i])
}
}
return count;
}
console.log(pairNumbers([10, 10, 10, 10, 20, 20, 20, 30, 50])) // 3
I'd reduce into an object, counting up the number of occurrences of each number. Then reduce again on the Object.values of the object to count up the number of pairs, adding Math.floor(count / 2) to the accumulator on each iteration:
function pairNumber(arr) {
const itemCounts = arr.reduce((a, item) => {
a[item] = (a[item] || 0) + 1;
return a;
}, {});
return Object.values(itemCounts)
.reduce((pairsSoFar, count) => pairsSoFar + Math.floor(count / 2), 0);
}
console.log(pairNumber([10, 10, 10, 10, 20, 20, 20, 30, 50]))
Probably better to avoid .sort if possible - that increases the computational complexity from O(n) (minimum) to O(n log n).
If I understood the question well then this can be simplified even further by relying on sort initially...
Increment i to the next position after finding the pair and let the for loop increment it once again.
function pairNumber(arr) {
const sorted_arr = [...arr].sort(); // disallowing array mutation
let cnt = 0;
for (let i = 0; i < sorted_arr.length; i++) {
if (sorted_arr[i + 1] === sorted_arr[i]) {
cnt++;
i = i + 1;
}
}
return cnt;
}
console.log(pairNumber([10, 10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 50]))
// 5 --> 2 pairs of 10, 2 pairs of 20, 1 pair of 30
console.log(pairNumbers([10, 10, 10, 10, 20, 20, 20, 30, 50]))
// 3 --> 2 pairs of 10 one pair of 20
Many thanks to all guys that help me understand more how to solve this issue.
After studying the answers in the post I come up with my own solution.
Thanks to you I understand I should increment i at the end of if to prevent a repetitive comparison.
function pairNumbers(arr) {
const sorted_arr = arr.sort();
const results = [];
for (let i = 0; i < sorted_arr.length; i++) {
if (sorted_arr[i] == sorted_arr[i + 1]) {
results.push(sorted_arr[i]);
i = i + 1;
}
}
return results.length;
}
console.log(pairNumbers([10, 10, 10, 10, 20, 20, 20, 30, 50])) // 3

Get similiar/closest numbers from the array

I'm trying to find the efficient way of finding the similar numbers (where the difference between the numbers is "almost constant" - close to some constant).
For example having array like:
const arr = [23, 130, 142, 151, 163, 200];
would return a new array:
const similarNumbers = [130, 142, 151, 163];
Currently the way I try to solve it is to map through the first array and try to find smallest difference between the numbers and then map again and check if the absolute value of currentValue - previousValue - smallestGap < SOME_THRESHOLD, but this is not ideal and only works in some of the particular cases.
Ideally what I'd like to achieve is for the function to return a few arrays with the grouped similar numbers:
const someArr = [23, 130, 142, 151, 163, 200, 232, 261];
would return two arrays:
group1 = [130, 142, 151, 163];
and:
group2 = [200, 232, 261];
This is a simple (and not perfect) function I just wrote. It will group numbers into groups based on a threshold value which defines the maximum derivation from the groups average.
const someArr = [23, 130, 142, 151, 163, 200, 232, 261];
var threshold = 50;
var relations = {};
var groups = {};
i = 0;
for (var j = 0; j < someArr.length; j++) {
var number = someArr[j];
if (i == 0) {
relations[number] = i;
groups[i] = [];
groups[i].push(number);
}
else {
var added = false;
var n_groups = 0;
for (var g in groups) {
var sum = 0;
var group = groups[g];
if (group.length == 1 && Math.abs(number - group[0]) <= 2 * threshold) {
relations[number] = parseInt(g, 10);
groups[g].push(number);
added = true;
}
else {
for( var n = 0; n < group.length; n++ ){
sum += group[n];
}
var avg = sum/group.length;
if (Math.abs(number - avg) <= threshold) {
relations[number] = parseInt(g, 10);
groups[g].push(number);
added = true;
}
}
n_groups++;
}
if (!added) {
var h = n_groups;
relations[number] = parseInt(h, 10);
groups[h] = [];
groups[h].push(number);
}
}
i++;
}
//console.log(relations, groups);
document.getElementById('grouped').innerHTML = JSON.stringify(groups);
<h3>Input</h3><div id="original">[23, 130, 142, 151, 163, 200, 232, 261]</div>
<h3>Output</h3><div id="grouped"></div>
I'm not sure it's the result you want to obtain.
function(entries) {
let groups = {};
let finalGroups = {};
for (var i = 0; i < entries.length; i++) {
let b = entries[i];
let power = 0;
while(b > 10) {
power++;
b = b / 10
}
groups[power] = groups[power] || []
groups[power].push(a[i]);
}
for (let i in groups) {
for (let j = 0; j < groups[i].length; j++) {
const c = groups[i][j]
const max = Math.floor(c / Math.pow(10, i));
finalGroups[i] = finalGroups[i] || {};
finalGroups[i][max] = finalGroups[i][max] || [];
finalGroups[i][max].push(c);
}
}
return finalGroups;
}
Here is the result. You will need to extract arrays but that's not the difficult part
{
"1":
{
"2":[23]
},
"2":
{
"1":[130,142,151,163],
"2":[200,232,261]
}
}
The function will firstly sort entries by their powers of 10. Then it will sort them by the number the most on the left.
So if you have values like 1030 and 1203 they will be considered as close values...
EDIT: Made a mistake. Fixed it
If you're wanting to find two groups of numbers that are more alike with each other, for the simplest sets you can split them in half, and find the difference between the first/last items, and the difference between the item before/after that item, if its closer to the item in the other group, else leave them as they are
const someArr = [23, 130, 142, 151, 163, 200, 232, 261];
someArr.sort((a, b) => a < b ? -1 : 1);
let groupA = someArr.slice(0, Math.ceil(someArr.length / 2))
let groupB = someArr.slice(Math.ceil(someArr.length / 2));
const differenceInA = Math.abs(groupA[groupA.length - 2] - groupA[groupA.length - 1]);
const differenceInB = Math.abs(groupB[0] - groupB[1]);
const differenceInBoth = Math.abs(groupA[groupA.length - 1] - groupB[0])
if (differenceInBoth < differenceInB) {
groupA.push(groupB[0]);
groupB = groupB.slice(1);
} else if(differenceInBoth > differenceInA) {
groupB.unshift( groupA[groupA.length - 1]);
groupA = groupA.slice(0, groupA.length - 1);
}
console.log('Group A:', groupA);
console.log('Group B:', groupB);
The above logs
Group A: [
23,
130,
142,
151,
163
]
Group B: [
200,
232,
261
]

Converting to Roman Numerals in Javascript - Weird bug

function convertToRoman(num) {
var thisMap = {
1:[1],
2:[1, 1],
3:[1, 1, 1],
4:[1, 5],
5:[5],
6:[5, 1],
7:[5, 1, 1],
8:[5, 1, 1, 1],
9:[1, 10],
0:[0]
};
var numMap = {
1000:"M",
500:"D",
100:"C",
50:"L",
10:"X",
5:"V",
1:"I"
};
numArr = num.toString().split("");
var thisIndex = 1;
var tallyArr = [];
for (var i = numArr.length - 1; i >= 0; i--) {
tallyArr.unshift(thisMap[numArr[i]]);
}
thisIndex = Math.pow(10, tallyArr.length - 1);
checkArr = [];
<<<BUG HERE>>>
for (var x = 0; x < tallyArr.length; x++) {
for (var y = 0; y < tallyArr[x].length; y++) {
tallyArr[x][y] *= thisIndex;
}
thisIndex = thisIndex / 10;
}
<<</BUG HERE>>>
var finalArr = [];
for (var a = 0; a < tallyArr.length; a++) {
for (var b = 0; b < tallyArr[a].length; b++) {
finalArr.push(numMap[tallyArr[a][b]]);
}
}
finalAnswer = finalArr.join("");
return finalAnswer;
}
convertToRoman(88);
So this is my function for converting a number into a Roman Numeral in Javascript. It basically formats every number into the right format using thisMap, then uses thisIndex to multiply by either 1000, 100 or 10, and then compares to numMap to get the correct Roman Numeral.
It seems to work in most of the test cases, except with 44, 99, or 3999.
In these cases, it seems to multiply the numbers by the wrong amount, so 44 becomes XLXL, when it should be XLIV.
I think the bug is between the <<>> tags I've inserted, because that is where the numbers seem to be multiplied wrong.
However, I can't spot the problem.
Thanks.
I tried a different approach.
function convertToRoman(num) {
let arabicArray = [ 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000, 4000, 5000, 5001]
let romanArray = ['I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M', 'MV', 'V', 'limit of 5000']
let roman = ""
loop()
function loop() {
for (let i = 0; i < arabicArray.length; i++) {
if (num < arabicArray[i]) {
roman += romanArray[i - 1]
num -= arabicArray[i - 1]
while (num != 0) {loop()} break;
}
}
}
return roman
}
console.log(convertToRoman(3))
However this gives you a limit to 5000.
Try this: x loop should run through all the length of tallyArr except the last one.
function convertToRoman(num) {
// ... code ...
for (var x = 0; x < tallyArr.length - 1; x++) {
for (var y = 0; y < tallyArr[x].length; y++) {
tallyArr[x][y] *= thisIndex;
}
thisIndex = thisIndex / 10;
}
// ... more code ...
}
Your solution seems a bit over engineered and overly complicated sometimes simpler is better and what might seem like a clever answer and looking for the overly eloquent solution can trip you up.
function convertToRoman(num) {
var output = "";
var numMap = [
{ limit: 1000, value: "M" },
{ limit: 900, value: "CM" },
{ limit: 500, value: "D" },
{ limit: 400, value: "CD" },
{ limit: 100, value: "C" },
{ limit: 90, value: "XC" },
{ limit: 50, value: "L" },
{ limit: 40, value: "XL" },
{ limit: 10, value: "X" },
{ limit: 9, value: "IX" },
{ limit: 5, value: "V" },
{ limit: 4, value: "IV" },
{ limit: 1, value: "I" }
];
for(var index = 0; index < numMap.length; index++) {
var value = numMap[index].value,
limit = numMap[index].limit;
while(num >= limit) {
output += value;
num -= limit;
}
}
return output;
}
alert(convertToRoman(1));
alert(convertToRoman(4));
alert(convertToRoman(5));
alert(convertToRoman(9));
alert(convertToRoman(10));
alert(convertToRoman(88));
alert(convertToRoman(2016));
JSFiddle
var romanNumber = [
[1, 'I'], [2, 'II'], [3, 'III'],[4, 'IV'],
[5, 'V'], [6, 'VI'],[7, 'VII'], [8, 'VIII'],
[9, 'IX'],[10, 'X']
];
function convertToRoman(number) {
if (number === 0) {
return '';
}
for (var i = 0; i < romanNumber.length; i++) {
if (number === romanNumber[i][0]) {
return romanNumber[i][1];
}
}
}
console.log(convertToRoman(1));
console.log(convertToRoman(2));
console.log(convertToRoman(3));
console.log(convertToRoman(4));
console.log(convertToRoman(5));
console.log(convertToRoman(6));
console.log(convertToRoman(7));
console.log(convertToRoman(8));
console.log(convertToRoman(9));
console.log(convertToRoman(10));

Obtain value from JSON variable inside javascript

How to obtain value from JSON element being created dynamically. Example below. I was wondering if there is way to get the value from previous element 'top' using some javascript. (Please update the title if its incorrect or misleading)
Following this example on jsfiddle
var info = [
{
src: "http://dummyimage.com/55x80/0d0.png/fff",
pos: {
top: 93,
left: 70
},
rotate: -10,
zIndex: 3
},
{
src: "http://dummyimage.com/55x80/d00.png/fff",
pos: {
top: previousElement(top) + some dynamic value added at run time,
left: 70
},
rotate: 0,
zIndex: 2
},
]
I wouldn't do this, you can calculate it as you go based on the index.
But... if you insist:
Assuming your array is a JS literal (and not JSON, which is different) you can use a simple counter.
Using the fact assignment returns the assigned value (this is kind of ugly though):
var top = 93;
var info = [
{
src: "http://dummyimage.com/55x80/0d0.png/fff",
pos: {
top: top,
left: 70
},
rotate: -10,
zIndex: 3
},
{
src: "http://dummyimage.com/55x80/d00.png/fff",
pos: {
top: top = top + (some dynamic value added at run time),
left: 70
},
rotate: 0,
zIndex: 2
} //... keep doing top = top + sometDynamicValue on all elements
]
A more isolated example might be:
var c = 0,
arr = [
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
{a:c = c + 5},
]
Which creates an array of objects with an increasing by 5 a property.
I was wondering if there is way to get the value from previous element 'top' using some javascript
info is an array so all you need to do is index into it then access the prop object i.e.
var prevTop = info[someIndex].pos.top;
There's no simple syntax to get the value from the previous element in an array literal in Javascript. You have to reference it by index, like this:
pos: {
top: info[0].pos.top + value
left: 70
},
Try this function:
function DoOffset(data, offset)
{
for (var i = 1; i < data.length; i++)
{
data[i].pos.top = data[i - 1].pos.top + offset;
}
}
You can loop through the info array to change the value:
for(var i = 1, len = info.length; i < len; i++) {
info[i].pos.top = info[i - 1].pos.top + newValue;
}

Categories

Resources