.sort is not a function on an array - javascript

Steps to reproduce:
1: Visit https://www.chess.com/play/computer
2: Paste JS code in the console
Expected results:
Pieces are printed by their square number ascendingly
Actual results:
Uncaught TypeError: newPieces.sort is not a function error is thrown
JS code:
pieces = ["r","n","b","q","k","p"];
colors = ["w","b"];
squareTemplate = "square-";
boardTemplate = "chess-board.layout-board";
function updatePieces(){
return document.querySelectorAll("chess-board.layout-board .piece");
}
function getFen(isFlipped){
}
function evalMove(){
}
console.log("Starting up ...");
const board = document.querySelector(boardTemplate);
let newPieces = [];
newPieces = updatePieces();
newPieces.sort(function(a,b){return a.classList[2].split('-')[1] - b.classList[2].split('-')[1]});
let fenRows = [];
for(i=0;i<newPieces.length;i++){
let classList = newPieces[i].classList;
let pieceColor = classList[1][0];
let pieceType = classList[1][1];
let pieceSquare = classList[2].split('-')[1];
//console.log(" Piece color is: " + pieceColor + " it is: " + pieceType + " and it is in: " + pieceSquare);
if(pieceColor == 'w'){
pieceType.toUpperCase();
} else {
pieceType.toLowerCase();
}
fen
}
So, basically JS is trying to tell me that is not an array, well, if it is not an array, then I am born in Bangladesh, because it is let newPieces = [];

updatePieces function in not returning an array, and sort method only work on array's, please first check updatePieces() function output

sort() is a method located on the Array.prototype which is what you want to use where as querySelectorAll() returns a static NodeList representing a list of the document's elements that match the specified group of selectors not an array. this is why your getting your exception. if you wish to use sort, you need to convert it into an array.
You can convert it to an array using array.from
const pieces = document.querySelectorAll("chess-board.layout-board .piece");
const arr = Array.from(pieces);

Related

Retrieving only the names from an xml file and putting them into an array in JavaScript

// https://www.w3schools.com/xml/simple.xml
// I am given the above xml file which has menu item names along with other things (price, calories, etc.) and I need to put only the names into an array using JavaScript coding. I'm using repl.it, and I already saved the file as a .xml on the side of my program. I just need to know how to extract only the names into an array. For example, the array should look like: [Belgian Waffles, Strawberry Belgian Waffles, (and so on)].
// In addition, I need to put the calories, the price, and the other stuff in separate arrays but I'm sure if I learn how to make an array for one thing I can do the other arrays too.
// In the past, I made this code to retrieve scores from a file with a list of scores (open repl.it link from the comments to see it in action):
// This program uses a file which has 6 peoples scores to calculate and display the max., min., and ave. scores and also puts them in an array. The program reads the file, trims out the strings so only the numbers are left & converted to numbers, limits the average score to the hundreths place, and verifies the file exists. The number of scores can be changed from 6 and the program would still work.
// Reference(s): https://www.w3schools.com/jsref/jsref_tofixed.asp
// https://codeburst.io/javascript-arrays-finding-the-minimum-maximum-sum-average-values-f02f1b0ce332
// Repl.it link: https://repl.it/live/AFSloyKSNJQjlA
main();
function main() {
var filename = "scores.txt";
if(!fileExists(filename)) {
console.log(`File ${filename} is missing.`)
return
}
var scores = [];
var scores = readFile("scores.txt");
console.log(scores);
var maximum = getMax(scores);
console.log("Maximum score: " + maximum)
var minimum = getMin(scores);
console.log("Mininum score: " + minimum);
var sum = getSum(scores);
var ave = sum / scores.length;
var ave = ave.toFixed(2);
console.log("Average score: " + ave);
}
function fileExists(filename) {
var fs = require('fs');
return fs.existsSync(filename);
}
function readFile(filename) {
var fs = require('fs');
var scores = [];
var contents = fs.readFileSync(filename, 'utf8');
lines = contents.split('\n');
for (var index = 0; index < lines.length; index++) {
var pos = lines[index].indexOf(',') + 1;
var scoreStr = lines[index].substring(pos).trim();
var score = Number(scoreStr);
if (!isNaN(score)) {
scores.push(score);
}
}
return scores;
}
function getMax(scores) {
scores.sort(function(a, b){return b - a});
var maximum = scores[0];
return maximum;
}
function getMin(scores) {
scores.sort(function(a, b){return a - b});
var minimum = scores[0];
return minimum;
}
function getSum(scores) {
return scores.reduce(function(a,b){
return a + b
}, 0);
}
There are two ways you can go about this. If you have a string of the XML you need to run through, and all you need is the contents of a single tag type, you can run that string through this regular expression to get what you need:
// xmlString is a string with the whole XML document in it
const foods = xmlString.match(/(?<=<name>)[A-Za-z ]+(?=<\/name>)/g);
If you want to get it by traversing the XML DOM, you can use JavaScript's standard DOM manipulation tools, like this:
const foodTagList = document.querySelectorAll('food name'); // selects all name nodes under food nodes
const foodList = [];
foodTagList.forEach((el) => foodList.push(el.innerHTML)) // can't use .map because foodTagList isn't an array
console.log(foodList); //prints the list of foods in array form
Finally, if you have the XML in string form and you want to do DOM traversal, you can run it through DOMParser's parseFromString method and then use the instructions for DOM traversal above.

Print Object like console.log (with a lot of information) in javascript

I need to send an email that contains the console.log output of a JS object. Here a code example:
let array_multi = [];
array_multi["07:00"] = ["one","two","three"];
array_multi["08:00"] = ["foo","bar","foo"];
array_multi["09:00"] = ["lorem"];
console.log(array_multi);
In my console result like this:
Is there some method to get this output in plain text, or should I write a custom parsing function?
If you are using JSON.stringify, you'll get the complete data, however there are a few downsides:
Arrays string properties, functions and other data structures get ignored completely (therefore serializing your data as is won't work¹)
circular references fail to serialize
There is no way to see inheritance from that
In your case you could do:
let array_multi = {};
array_multi["07:00"] = ["one","two","three"];
array_multi["08:00"] = ["foo","bar","foo"];
array_multi["09:00"] = ["lorem"];
// logs as object
console.log(array_multi);
console.log(typeof array_multi);
// parse and convert to string
console.log(JSON.stringify(array_multi));
console.log(typeof JSON.stringify(array_multi));
In Node.js you've got another option, which is util.format, which will return the same content as a string that you can see in the Node.js console. While it does give you a great insight into the different datatypes and relationships, it cannot show you the same infinite tree that an interactive console is able to show, so it will only show you a small part of the big picture.
¹: Your array_multi should actually be an object, not an array, as arrays should only have numeric keys.
After a lot of search the right method is write a custom function (chrome have once inside dev tools core)
here the solution:
let array_multi = [];
array_multi["07:00"] = ["one","two","three"];
array_multi["08:00"] = ["foo","bar","foo"];
array_multi["09:00"] = ["lorem"];
function print_js_element(elm, show_content = false){
let output_res = "{\n";
let object_keys = Object.keys(elm);
object_keys.some(function(key,index) {
output_res += "\t" + key + ": (" + elm[key].length + ")";
if(show_content){
output_res += " " + JSON.stringify(elm[key]);
}
output_res += "\n";
});
output_res += "\n}";
return output_res;
}
console.log(print_js_element(array_multi,false));
console.log(print_js_element(array_multi,true));
Covert this array into an object first:
let array_multi = [];
array_multi["07:00"] = ["one","two","three"];
array_multi["08:00"] = ["foo","bar","foo"];
array_multi["09:00"] = ["lorem"];
let arrObj = {...array_multi};
console.log(JSON.stringify(arrObj));

Javascript Appending to 2-D Array

I am trying to append an array to an array. I am expecting the output to be something like:
[[Dep,POR],[14073,99.25],[14072,0.06]]
But I am getting:
Dep,POR,14073,99.25,14072,0.06
Here's what I have so far:
function get_historical() {
var well = document.getElementById('wellSelect');
var selected_well = well.options[well.selectedIndex].value;
var hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
hist_por = ['Dep','POR'];
for (var item in hist_json_obj) {
if (hist_json_obj.hasOwnProperty(item)) {
var dep = hist_json_obj[item].dep;
var por = hist_json_obj[item].por;
var arr_por = [dep, parseFloat(por)];
hist_por.push(arr_por);
}
}
document.write(hist_por);
}
When you initialize hist_por, you want that to be a 2-D array whereas you currently have just a single array. So you would want to change its instantiation to:
hist_por = [['Dep','POR']]; // [[ ... ]] instead of [ ... ]
Also per #justrusty's answer, you need to JSON.stringify(hist_por) when you pass it to document.write(). This is the more important piece so his answer should be accepted.
So the whole code block would become:
function get_historical() {
var well = document.getElementById('wellSelect');
var selected_well = well.options[well.selectedIndex].value;
var hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
hist_por = [['Dep','POR']];
for (var item in hist_json_obj) {
if (hist_json_obj.hasOwnProperty(item)) {
var dep = hist_json_obj[item].dep;
var por = hist_json_obj[item].por;
var arr_rop = [dep, parseFloat(por)];
hist_por.push(arr_por);
}
}
document.write(JSON.stringify(hist_por));
}
This may help you https://codepen.io/anon/pen/xQLzXx
var arr = ['foo','bar'];
var arr2 = ['baz', 'boo']
arr.push(arr2);
console.log(arr);
document.write(arr);
document.write("<br>");
document.write(JSON.stringify(arr));
It's basically just the way it writes it to document. If you log it in console you'll see the array appended. Or if you JSON.stringify() first it will show as you expect.
My advice is ALWAYS console.log() so you can see exactly how the data is structured
The others have already pointed out what the problem is (+ there's a typo in one of your variable names - arr_rop vs arr_por). Here's an ES6 version that will break in older browsers, for learning purposes:
function get_historical() {
const well = document.getElementById('wellSelect');
const selected_well = well.options[well.selectedIndex].value;
const hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
const hist_por = Object.values(hist_json_obj).reduce(
(arr, item) => [...arr, [item.dep, +item.por]],
[["Dep", "POR"]]
);
document.write(JSON.stringify(hist_por));
}

JavaScript Array.shift not working

I have been programming a system that is supposed to delete the first index of an array. Instead of changing an array from (i.e) "1,2,3,4,5" to "2,3,4,5" the console gives an error: "Uncaught TypeError: num.splice is not a function". I have heard that num.splice is not a function, it is an operation (or something) to delete the first indexed value of the array. I am confused that when I use an example code from w3Schools, there is no outputted error in the console. I don't understand why this happens.
(I have given the entire code just in case it has to do with syntax issues)
function dCrypt() {
var num = document.getElementById("demoin").value; // ex: a127
var key = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var mod = 0;
var out = 0;
var prep = 0;
var pre = 0;
num.split("");
mod = num[0];
pre = key.indexOf(mod);
num.splice(0,1);
for (i=0;i <= pre;i++) {
prep += 26;
}
out = Math.floor(num + pre);
document.getElementById("demoout").innerHTML = out;
}
Thanks in advance!
When you split 'num' you have to reassign it
num = num.split("");
Referring to your link from w3schools:
The splice() method adds/removes items to/from an array, and returns the removed item(s).
As you can see the var num is string(and not an array) and has the value of the element with id demoin.
Since you are trying to splice a string and not an array. The error shows up in the console.
Solution:
Either store the value of your split in an array(it could be num itself) and then splice that array.
num = num.split("");
...
num.splice(0,1);

reading all the submatches in regexp multiple matches

today i'm trying to parse a 'ps aux' output (issued from a node.js server)
so i made an happy regex to parse the values, and i wanted to put all those fancy informations into a simple JSON object :-)
problem is, the regex i've made has 3 match groups, doing multiple matches... and i don't even know if it's possible to have it all the matches returned.
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var re_ps = /(?:([\d\.\w\-\?\/\+]+)\s+){8}(?:((?:\d+\:\d+)|(?:\w+\d+))\s+){2}([^\n]+)/g,
result_re_ps,
array_re_ps = [];
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=1; i < 2; i++){
while ((result_re_ps = re_ps.exec(split_data[i])) != null){
console.log("--- while iteration ---");
console.dir(result_re_ps);
//console.dir(result_re_ps);
}
}
//http_resp.write(data);
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
the "--- while iteration ---" it's just one per each line, instead, it should be multiples!
I will link a fancy screenshot to let you visually understand what kind of data i'm expecting
As you can see the above are 3 groups of data, each one with multiple occurrences
Any help? :p
EDITED TO CLARIFY:
This is the result of a line like:
root 5213 0.0 2.1 8688 2760 ? Ss 11:33 0:01 sshd: root#pts/0
As you can see, the resulting array is 1-dimensional, instead for the results to be contained entirely it HAS to be at least 2-dimensional
UPDATE:
For now i've solved the problem changin my code like this:
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var array_re_ps = [];
var re_ps1 = /(?:([\d\.\w\-\?\/\+]+)\s+)/g,
re_ps2 = /(?:((?:\d+\:\d+)|(?:\w+\d+))\s+)/g,
re_ps3 = /([^\n]+)/g;
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=20; i < 21; i++){
array_re_ps[0] = [], array_re_ps[1] = [];
for (var j=0; j<8; j++){
array_re_ps[0].push(re_ps1.exec(split_data[i])[1]);
}
re_ps2.lastIndex = re_ps1.lastIndex;
for (var j=0; j<2; j++){
array_re_ps[1].push(re_ps2.exec(split_data[i])[1])
}
re_ps3.lastIndex = re_ps2.lastIndex;
array_re_ps[2] = re_ps3.exec(split_data[i])[1];
console.dir(array_re_ps);
}
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
Basically i split my long regexp, in 3 smaller ones, and i do cycle through their results.
If you try the code i formatted the resulting array exactly as i wanted, but i still think that it's a side-solution.
Since Regular Expressions lets you "multiple parse group multiple times", it is possible to have that functionality in javascript?
Take a look at the return values of the exec function.
It returns the index where it first matched, the original string and the capture groups in the elements [0]...[n].
All this is available in your output, you just have to iterate through the single elements of the array.

Categories

Resources