Related
I have this .txt file to change to a nested array:
000011000000
000100001100
000001100001
010010001000
100101000100
101010010001
001000001001
000001000111
010100100010
010010010010
000000011100
001001110000
to the format:
var data = [
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1],
[0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0]
]
what I have done so far is:
Read the file:
function readMatrixFile(){
var inputElement = document.getElementById("adjencyMatrixInput");
var fileList = inputElement.files;
var plainMatrix = new FileReader();
plainMatrix.readAsText(fileList[0]);
plainMatrix.onload = function () {
//Add to Matrix
renderMatrix(plainMatrix)
}
}
and
2. Split the File
function renderMatrix(plainMatrix) {
var matrix = plainMatrix.result;
var mtx = [];
matrix = matrix.split("\n");
}
I know I need to push through a for loop, but not sure how to get the nested array.
Split the string by a newline, then map over each item and convert the string into an array of characters with spread syntax.
const str = `000011000000
000100001100
000001100001
010010001000
100101000100
101010010001
001000001001
000001000111
010100100010
010010010010
000000011100
001001110000`
const res = str.split("\n").map(e => [...e])
console.log(res)
To convert the characters to numbers, map over the array of characters and parse each item:
const str = `000011000000
000100001100
000001100001
010010001000
100101000100
101010010001
001000001001
000001000111
010100100010
010010010010
000000011100
001001110000`
const res = str.split("\n").map(e => [...e].map(e => +e))
console.log(res)
You turn matrix into a a string of ones and zeros, you just need to split the string and convert them to numbers
function renderMatrix(plainMatrix) {
var matrix = plainMatrix.result;
var mtx = matrix.split("\n"); // mtx is now an array of strings of ones and zeros
mtx = mtx.map(string => string.split('')); // mtx is now an array of arrays of number string
mtx = mtx.map(nested => nested.map(numberString => Number(numberString))); // mtx is now what you want
}
I apologize if this is not well explained. I am quite new to JavaScript.
I have a 2D arrayA that is 10x10 and a 2D arrayB that is 5x8. The smaller arrayB is populated with data and the larger arrayA is just populated with 0's by default.
How can i move the data from arrayB to arrayA while still leaving the leftover space of arrayA as 0's?
The end result must be that arrayA should contain all of the data in the same order as arrayB but with the leftover space still just containing 0's.
Assuming I understood the question correctly, you can loop over each value of arrayB and assign it at the same indexes in arrayA:
const arrayA = Array(10).fill(0).map(_ => Array(10).fill(0))
const arrayB = Array(5).fill(0).map(_ => Array(8).fill(1))
for (let y = 0; y < arrayB.length; y++) {
for (let x = 0; x < arrayB[y].length; x++) {
arrayA[y][x] = arrayB[y][x]
}
}
console.log(arrayA.map(v => v.join(', ')).join('\n'))
The console.log is just for readability, to understand how the matrix looks.
A simple Array.map() will do the job:
const arrA = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
const arrB = [
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
[0,1,2,3,4],
];
const B2A = () => arrA.map(
(val, index) => val.map(
(subVal, subIndex) => {
if(arrB[index] && arrB[index][subIndex]) return arrB[index][subIndex]
return subVal;
})
)
console.log(B2A());
Use Array.from and iterate, while iterate check if the value exists in filler array. If exists use that value otherwise same array value.
const fill = (arr1, arr2) =>
Array.from(arr1, (arr, row) =>
Array.from(arr, (value, col) => (arr2[row] && arr2[row][col]) || value)
);
const arrA = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
const arrB = [
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
];
console.log(JSON.stringify(fill(arrA, arrB)));
JAVASCRIPT - JQUERY
sum the values
How to group the first value (the date) and add the values of the same dates?
ARRAY :
0: (5) ["11-2019", 0, 20, 0, 0]
1: (5) ["11-2019", 41, 0, 0, 0]
2: (5) ["11-2019", 0, 0, 29, 0]
3: (5) ["11-2019", 0, 0, 0, 60]
4: (5) ["09-2019", 0, 1, 0, 0]
5: (5) ["09-2019", 0, 0, 1, 0]
6: (5) ["09-2019", 0, 0, 0, 1]
7: (5) ["05-2019", 2, 0, 0, 0]
OUT :
0: (5) ["11-2019", 41, 20, 29, 60]
1: (5) ["09-2019", 0, 1, 1, 1]
2: (5) ["05-2019", 2, 0, 0, 0]
result = DataAll.reduce(function(r, a) {
a.forEach(function(b, i) {
r[i] = (r[i] || 0) + b;
console.log(r[i]);
});
return r;
}, []);
I would find the array in the result set and update all values.
var data = [["11-2019", 0, 20, 0, 0], ["11-2019", 41, 0, 0, 0], ["11-2019", 0, 0, 29, 0], ["11-2019", 0, 0, 0, 60], ["09-2019", 0, 1, 0, 0], ["09-2019", 0, 0, 1, 0], ["09-2019", 0, 0, 0, 1], ["05-2019", 2, 0, 0, 0]],
result = data.reduce((r, a) => {
var temp = r.find(([date]) => date === a[0])
if (temp) {
for (var i = 1; i < a.length; i++) temp[i] += a[i];
} else {
r.push([...a]);
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I added a filter to your script to remove the 0-values from the results. If you really want the 0 values use
acc[curr[0]]=(acc[curr[0]]||[]).concat(curr.slice(1));
instead.
var inp=[["11-2019", 0, 20, 0, 0],
["11-2019", 41, 0, 0, 0],
["11-2019", 0, 0, 29, 0],
["11-2019", 0, 0, 0, 60],
["09-2019", 0, 1, 0, 0],
["09-2019", 0, 0, 1, 0],
["09-2019", 0, 0, 0, 1],
["05-2019", 2, 0, 0, 0]];
var out=inp.reduce((acc,curr)=>{
acc[curr[0]]=(acc[curr[0]]||[]).concat(curr.slice(1).filter(v=>v>0));
return acc
}, {});
console.log(out);
// and to get it into your format:
var outarr=Object.keys(out).map(k=>[k].concat(out[k]))
console.log(outarr)
Right, if you want the sum then my version would be the following. Thanks to Nina for supplying a correct answer first. ;-)
var inp=[["11-2019", 0, 20, 0, 0],
["11-2019", 41, 0, 0, 0],
["11-2019", 0, 0, 29, 0],
["11-2019", 0, 0, 0, 60],
["09-2019", 0, 1, 0, 0],
["09-2019", 0, 0, 1, 0],
["09-2019", 0, 0, 0, 1],
["05-2019", 2, 0, 0, 0]];
let out=inp.reduce((acc,cur)=>{
if(acc[cur[0]]) acc[cur[0]].forEach((v,i,a)=>a[i]+=cur[i+1]);
else acc[cur[0]]=cur.slice(1)
return acc
}, {} );
outarr=Object.keys(out).map(k=>[k].concat(out[k]))
console.log(outarr)
I'm trying to fill an area in a multidimensional array and not sure on the approach.
For example I have the following array:
var map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0],
[0, 2, 0, 0, 0, 0, 2, 0, 0],
[0, 2, 0, 2, 0, 0, 2, 0, 0],
[0, 2, 0, 0, 2, 0, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 2, 2, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
And then I am trying to get the number from X and Y position and fill all those numbers (which is 0) with a number given such as 1, which will result in the following array:
var map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0],
[0, 2, 1, 1, 1, 1, 2, 0, 0],
[0, 2, 1, 2, 1, 1, 2, 0, 0],
[0, 2, 1, 1, 2, 1, 2, 0, 0],
[0, 0, 2, 1, 1, 1, 2, 0, 0],
[0, 0, 0, 2, 2, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
Basically just replacing all numbers next to each other (0) with (1) within that area.
What is the correct way to do this with JavaScript?
Assuming you're given a starting position and you want to then fill all neighboring values up/down, left/right that contain the same value, you can do something like this:
var map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0],
[0, 2, 0, 0, 0, 0, 2, 0, 0],
[0, 2, 0, 2, 0, 0, 2, 0, 0],
[0, 2, 0, 0, 2, 0, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 2, 2, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
function fill(data, x, y, newValue) {
// get target value
var target = data[x][y];
function flow(x,y) {
// bounds check what we were passed
if (x >= 0 && x < data.length && y >= 0 && y < data[x].length) {
if (data[x][y] === target) {
data[x][y] = newValue;
flow(x-1, y); // check up
flow(x+1, y); // check down
flow(x, y-1); // check left
flow(x, y+1); // check right
}
}
}
flow(x,y);
}
fill(map, 2, 2, 1);
Working demo: http://jsfiddle.net/jfriend00/C83AT/
Here's a version that doesn't use recursion and appears to work with large data sets. Your large test data set wasn't a very interesting test pattern so I wouldn't say this is tested conclusively, but it seems to work on both the small and large data set:
Large data example: http://jsfiddle.net/jfriend00/8mrhN/
Small data example: http://jsfiddle.net/jfriend00/BFTub/ (easier to see the result)
function fill(data, x, y, newValue) {
// get target value
var target = data[x][y];
// maintain list of cells to process
// put the starting cell in the queue
var queue = [{x:x, y:y}], item;
while (queue.length) {
item = queue.shift();
x = item.x;
y = item.y;
if (data[x][y] === target) {
data[x][y] = newValue;
// up
if (x > 0) {
queue.push({x:x-1, y:y})
}
// down
if (x + 1 < data.length) {
queue.push({x:x+1, y:y})
}
// left
if (y > 0) {
queue.push({x:x, y:y-1});
}
// right
if (y + 1 < data[x].length) {
queue.push({x:x, y:y+1});
}
}
}
}
This could be optimized further for performance by testing the value before putting it in the queue and by following a given direction until you find a non-matching value, if required.
This is an alternative implementation (queue-based) roughly translated, no optimisations performed. There are also others.
Javascript
var map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 2, 2, 2, 0, 0],
[0, 2, 0, 0, 0, 0, 2, 0, 0],
[0, 2, 0, 2, 0, 0, 2, 0, 0],
[0, 2, 0, 0, 2, 0, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 2, 2, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
/*
1. Set Q to the empty queue.
2. If the color of node is not equal to target-color, return.
3. Add node to Q.
4. For each element N of Q:
5. If the color of N is equal to target-color:
6. Set w and e equal to N.
7. Move w to the west until the color of the node to the west of w no longer matches target-color.
8. Move e to the east until the color of the node to the east of e no longer matches target-color.
9. For each node n between w and e:
10. Set the color of n to replacement-color.
11. If the color of the node to the north of n is target-color, add that node to Q.
12. If the color of the node to the south of n is target-color, add that node to Q.
13. Continue looping until Q is exhausted.
14. Return.
*/
function floodFill(data, node, targetValue, replacementValue) {
var Q;
if (data[node[0]][node[1]] === targetValue) {
Q = [node];
while (Q.length) {
var N = Q.shift(),
value,
index,
n,
e,
s,
w;
if (data.hasOwnProperty([N[0]]) && data[N[0]][N[1]] === targetValue) {
w = e = N[0];
do {
w -= 1;
} while (data.hasOwnProperty(w) && data[w][N[1]] === targetValue);
do {
e += 1;
} while (data.hasOwnProperty(e) && data[e][N[1]] === targetValue);
n = N[1] - 1;
s = N[1] + 1;
for (index = w + 1; index < e; index += 1) {
data[index][N[1]] = replacementValue;
if (data[index].hasOwnProperty(n) && data[index][n] === targetValue) {
Q.push([index, n]);
}
if (data[index].hasOwnProperty(s) && data[index][s] === targetValue) {
Q.push([index, s]);
}
}
}
}
}
}
floodFill(map, [2, 2], 0, 1);
map.forEach(function (m) {
console.log(JSON.stringify(m));
});
Output
[0,0,0,0,0,0,0,0,0]
[0,2,2,2,2,2,2,0,0]
[0,2,1,1,1,1,2,0,0]
[0,2,1,2,1,1,2,0,0]
[0,2,1,1,2,1,2,0,0]
[0,0,2,1,1,1,2,0,0]
[0,0,0,2,2,2,2,0,0]
[0,0,0,0,0,0,0,0,0]
On jsFiddle
I have been creating a game in HTML5 and javascript and have came across a problem.
The game uses a tile system to load the map. Currently my map is saved within a multidimensional array and looks like this:
var map = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
I would like to add move levels by using a XML file to update the array.
My XML file currently looks like this:
<TileMaps>
<Level level="1">
<map>[ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 2, 4, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
</map>
</Level>
<Level level="2">
<map>[ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
</map>
</Level>
</TileMaps>
If anyone could help me load level="1" into my map variable that would be great.
Thanks
Don't use xml, use json. Here's a link to what its about, http://www.json.org/.
While not entirely precise, its pretty safe to think of json as a subset of javascript.
For example:
{
"levels":[
[
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 2, 4, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
],
[
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 4, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
]
}
Use http://jsonlint.org to validate json.
For anyone who wanted to know i fixed this by using the following code:
req=new XMLHttpRequest();
req.open("GET","my.xml",false);
req.send();
xmlDoc = req.responseXML;
map = JSON.parse(xmlDoc.getElementsByTagName('map')[0].firstChild.nodeValue);