I have a full path to an image, which I am using jQuery to read like this:
$('img.my_image').attr('src');
However I just want the filename portion (i.e. without full path).
Are there any built-in functions to do this, or would a regex be the only option?
var Filename= path.split('/').pop()
var fileNameIndex = yourstring.lastIndexOf("/") + 1;
var filename = yourstring.substr(fileNameIndex);
function getFileName(path) {
return path.match(/[-_\w]+[.][\w]+$/i)[0];
}
I found a better version handling unix and windows-like path-strings.
Number 1:
var unix_path = '/tmp/images/cat.jpg';
console.log(unix_path.replace(/^.*[\\\/]/, ''));
var win_path = 'c:\\temp\images\cat.jpg';
console.log(win_path.replace(/^.*[\\\/]/, ''));
Output will be cat.jpg
Number 2: (maybe faster)
var unix_path = '/tmp/images/cat.jpg';
console.log(unix_path.split(/[\\\/]/).pop());
var win_path = 'c:\\temp\images\cat.jpg';
console.log(win_path.split(/[\\\/]/).pop());
Output will be cat.jpg
In Javascript you could do
function getFileNameFromPath(path) {
var ary = path.split("/");
return ary[ary.length - 1];
}
Using this solution you can get both names i.e. with and without file extension.
//getting image source
var path=$('img.my_image').attr('src');
//splitting url and getting filename with file extension
var file=path.split('/').pop();
//removing extension and keeping just the filename
var filename=file.split('.').shift();
Addition to accepted answer. Looks like here is fastest and cross platform (Unix and Windows) solution:
function basePath(path) {
return path.substr(
Math.max(
path.lastIndexOf('\\'),
path.lastIndexOf('/'),
) + 1,
);
}
It's necessary in situation, when you have data from both Unix and Windows and we have to parse in in one place.
This function just takes latest of all possible separators and returns string after last separator. It is much faster with big strings and that's why:
no regexps, they are slower then simple equality
no normalization, have no unconditionally go threw whole the string and make something new from it
no creating any new instances, like new arrays and so on, it takes some time and memory
no extra cycles or even lookups because we don't use arrays here
Tested in Chromex87:
// Test subjects
//=====================
function basePathUnix(path) {
return path.split('/').pop();
}
function basePathUnix2(path) {
const arr = path.split('/');
return arr[ arr.length - 1 ];
}
function basePathUnix3(path) {
return path.substr(path.lastIndexOf('/') + 1);
}
function basePathCrossPlatform(path) {
return path.replace(/^.*[\\\/]/, '');
}
function basePathCrossPlatform2(path) {
return path.split(/[\\\/]/).pop();
}
function basePathCrossPlatform3(path) {
return path.substr(Math.max(path.lastIndexOf('\\'), path.lastIndexOf('/')) + 1);
}
function basePathCrossPlatform4(path, separators = ['/', '\\']) {
return path.substr(Math.max(...separators.map(s => path.lastIndexOf(s))) + 1);
}
// Tests
//=====================
function measureTime(name, fn) {
const start = window.performance.now();
for (let i = 0; i < 10000; i++) {
fn();
}
const time = window.performance.now() - start;
console.log(name, time);
}
function testResults(name, path) {
console.log('\n[CHECK RESULTS]', name);
console.log('basePathUnix:\t\t', basePathUnix(path));
console.log('basePathUnix2:\t\t', basePathUnix2(path));
console.log('basePathUnix3:\t\t', basePathUnix3(path));
console.log('basePathCrossPlatform:\t', basePathCrossPlatform(path));
console.log('basePathCrossPlatform2:\t', basePathCrossPlatform2(path));
console.log('basePathCrossPlatform3:\t', basePathCrossPlatform3(path));
console.log('basePathCrossPlatform4:\t', basePathCrossPlatform4(path));
}
function testPerformance(name, path) {
console.log('\n[MEASURE PERFORMANCE]', name);
measureTime('basePathUnix:\t\t', () => basePathUnix(path));
measureTime('basePathUnix2:\t\t', () => basePathUnix2(path));
measureTime('basePathUnix3:\t\t', () => basePathUnix3(path));
measureTime('basePathCrossPlatform:\t', () => basePathCrossPlatform(path));
measureTime('basePathCrossPlatform2:\t', () => basePathCrossPlatform2(path));
measureTime('basePathCrossPlatform3:\t', () => basePathCrossPlatform3(path));
measureTime('basePathCrossPlatform4:\t', () => basePathCrossPlatform4(path));
}
function runTest(name, path) {
setTimeout(() => {
testResults(name, path);
setTimeout(() => {
testPerformance(name, path);
}, 200);
}, 200);
}
// Run tests
//=====================
setTimeout(() => {
const pathUnix = '/some/path/string/some/path/string/some/path/string/some/path/string/some/path/string/some/path/file-name';
runTest('UNIX', pathUnix);
}, 1000);
setTimeout(() => {
const pathWind = '\\some\\path\\string\\some\\path\\string\\some\\path\\string\\some\\path\\string\\some\\path\\file-name';
runTest('WINDOWS', pathWind);
}, 2000);
Related
Problem
I'm trying to implement some sort of "fuzzy search" in my Node.js based project.
Fuzzy search is a search that returns results even if the string didn't match exactly.
I found this code in another stackoverflow thread. Code is below.
It's quite good, but the problem is - it's synchronous It slows down the whole program when it searches through a large array.
Question
ES6 methods are welcomed. Needs to work only in the latest Chrome, so any JS methods will work.
Are there any new JS methods that would optimize this function?
Am I doing something wrong there that makes it even slower?
Can I turn this function into an async function that returns a promise? Will it stop freezing the app during the search then?
Are there any better "fuzzy search" implementations you know of? (I found a module called fuzzysort, can't say if it's that much better though, it won't return "folder test" if you type "test folder" (wrong order) so it's not that good)
Code
Calling search function
searchArray is an array of paths it searches through, e.g.: ["C:\\test", "C:\\file.txt"...] (0.5 - 5 million paths)
searchQuery is a string without spaces, e.g.: filetxt
search () {
const fuzzySearch = this.fuzzySearch(this.searchQuery.toLowerCase(), this.searchArray)
let result = fuzzySearch.filter(element => element.relevance >= 0.3)
// sort by relevance
var sortedResults = result.sort((a, b) => parseFloat(b.relevance) - parseFloat(a.relevance)).map(item => item.name);
this.searchResults = sortedResults
},
The fuzzy search function
fuzzySearch (searchQuery, searchArray) {
const get_bigrams = function(string) {
const s = string.toLowerCase();
const v = new Array(s.length - 1);
for (let i = 0, end = v.length; i <= end; i++) {
v[i] = s.slice(i, i + 2);
}
return v;
};
const string_similarity = function(str1, str2) {
if ((str1.length > 0) && (str2.length > 0)) {
const pairs1 = get_bigrams(str1);
const pairs2 = get_bigrams(str2);
const union = pairs1.length + pairs2.length;
let hit_count = 0;
for (let x of Array.from(pairs1)) {
for (let y of Array.from(pairs2)) {
if (x === y) {
hit_count++;
}
}
}
if (hit_count > 0) {
return ((2.0 * hit_count) / union);
}
}
return 0.0;
};
let results = [];
for (let name of searchArray) {
// I added .match to use only the base filename (name+ext) not the whole path, and removed all characters
let filteredPath = name.match(/[^\\\/]+$/)[0].replace(/[^A-Za-z0-9.]+/g, '')
const relevance = string_similarity(searchQuery, filteredPath);
const obj = {name, relevance};
results.push(obj);
}
return results
},
I have this simple function which will prepend a desired string to the beginning of each line. I have this working with streams, but in some cases it's also convenient using a console.log() type of construct.
Here is the function:
// takes a string to prepend, and a stream to prepend to:
exports.lp = function (str, strm) {
return function prependLog() {
var args = Array.from(arguments);
var hasNonWhitespace = args.some(function (a) {
var str = String(a);
return str.length > 0 && /\S/g.test(str);
});
if (hasNonWhitespace) {
strm.write(str);
}
args.forEach(function (s, i) {
String(s).split('\n').forEach(function (s, i) {
if (i < 1) {
strm.write(s + ' ');
}
else {
strm.write('\n' + str + s);
}
});
});
strm.write('\n');
};
};
Here is the use:
const {lp} = require('log-prepend');
const fn = lp(' [foobar] ', process.stdout);
fn('\n');
fn();
fn();
fn('','','');
fn('log1', 'log2\n3',4,5 + '\n55');
fn('a','b','c');
and here is the output from the above:
[foobar]
[foobar] log1 log2
[foobar] 34 5
[foobar] 55
[foobar] a b c
the problem is that for empty lines with no non-whitespace character, it usually works, but when I include a newline character, it outputs [foobar] even though there is nothing on that line.
I can't figure out why my function doesn't omit [foobar] for lines with no non-whitespace. So to be exact, it is the first instance of [foobar] above that is mystifying me.
Having a little trouble following the logic here but is it because you are expecting to use the index variable from the first forEach function, when it's actually using it from the second? Renaming the initial variables might help.
I think I made a good fix like so:
exports.lp = function (str, strm) {
return function prependLog() {
var args = Array.from(arguments);
var hasNonWhitespace = args.some(function (a) {
var str = String(a);
return str.length > 0 && /\S/g.test(str);
});
if (hasNonWhitespace) {
strm.write(str);
}
args.forEach(function (s, i) {
String(s).split('\n').forEach(function (s, i) {
if (i < 1) {
strm.write(s + ' ');
}
else {
// => here is the fix, add the following if/else
if (/\S/g.test(s)) {
strm.write('\n' + str + s);
}
else {
strm.write('\n' + s);
}
}
});
});
strm.write('\n');
};
};
but if anyone has a better way to do this, please let me know.
How can I detect the CSV separator from a string in Javascript/NodeJS?
Which is the standard algorithm?
Note that the separator is not a comma always. The most common separators being ;, , and \t (tab).
A possible algorithm for getting the likely separator(s) is pretty simple, and assumes the data is well-formed:
For every delimiter,
For every line,
Split the line by the delimiter, check the length.
If its length is not equal to the last line's length, this is not a valid delimiter.
Proof of concept (doesn't handle quoted fields):
function guessDelimiters (text, possibleDelimiters) {
return possibleDelimiters.filter(weedOut);
function weedOut (delimiter) {
var cache = -1;
return text.split('\n').every(checkLength);
function checkLength (line) {
if (!line) {
return true;
}
var length = line.split(delimiter).length;
if (cache < 0) {
cache = length;
}
return cache === length && length > 1;
}
}
}
The length > 1 check is to make sure the split didn't just return the whole line. Note that this returns an array of possible delimiters - if there's more than one item, you have an ambiguity problem.
Another solution is using the detect method from the csv-string package:
detect(input : String) : String Detects the best separator.
var CSV = require('csv-string');
console.log(CSV.detect('a,b,c')); // OUTPUT : ","
console.log(CSV.detect('a;b;c')); // OUTPUT : ";"
console.log(CSV.detect('a|b|c')); // OUTPUT : "|"
console.log(CSV.detect('a\tb\tc'));// OUTPUT : "\t"
function delimiter(csvText) {
t = t.split("\n")[0];
let delArray = [',', ';', '|', ' '];
let comma = samiclon = pipe = tab = 0;
delArray.forEach((e, i) => {
if (i === 0) {
comma = t.split(e).length;
} else if (i === 1) {
samiclon = t.split(e).length;
} else if (i === 2) {
pipe = t.split(e).length;
} else if (i === 3) {
tab = t.split(e).length;
}
});
let tmpArray1 = [comma, samiclon, pipe, tab]
let tmpArray = [comma, samiclon, pipe, tab];
let maxLen = tmpArray.sort((a, b) => b - a)[0];
let delimiter_i = 0;
tmpArray1.forEach((e, i) => {
if (maxLen === e) {
delimiter_i = i;
}
});
if (delimiter_i === 0) {
return ',';
} else if (delimiter_i === 1) {
return ';'
} else if (delimiter_i === 2) {
return '|'
} else if (delimiter_i === 3) {
return ' '
}
}
This solution allows to detect the csv separator only for the top lines and handles quoted fields by using csv-parse.
It can be useful for large csv file to avoid reading the whole file several times.
const parse = require('csv-parse/lib/sync');
const fs = require('fs')
function detectCsvDelimiter(file, maxLineCount, delimiters = [',', ';', '\t']) {
return new Promise((resolve, reject) => {
// Read only maxLineCount lines
let stream = fs.createReadStream(file, {
flags: 'r', encoding: 'utf-8', bufferSize: 64 * 1024 });
let lineCounter = 0;
let data = '';
stream.on("data", (moreData) => {
data += moreData;
lineCounter += data.split("\n").length - 1;
if (lineCounter > maxLineCount + 1) {
stream.destroy();
// Remove invalid last line
resolve(data.split('\n').slice(0, maxLineCount));
}
});
stream.on("error", (err) => reject(err));
stream.on("end", () => resolve(data.split("\n")));
}).then(lines => {
return new Promise(resolve => {
const csvData = lines.join("\n");
const validDelimiters = delimiters.filter(delimiter => {
let isValid = true;
// csv-parse throw error by default
// if the number of columns is inconsistent between lines
try {
const rows = parse(csvData, {delimiter});
isValid = rows.some(row => row.length > 1);
} catch (e) {
isValid = false;
}
return isValid;
});
resolve(validDelimiters);
});
});
}
I found Zirak's answer good in theory, but in practice it failed in many particular places.
Here are some examples that would fail and thus the method would return no delimiter :
a trailing delimiter (by mistake) : test,test1,test2,
missing cells without delimiters: test,test1
This is the most convenient and elegant solution :
let columnData = row.split(/,|;|\|| /);
What sucks here is if there is two delimiters that appear in a row, then this fails.
Say you want to seperate this data: "test,tes|t1,test2".
The above code produces an array that looks like this :
[test, tes, t1, test2]... No good.
Here is a more robust solution I wrote that was inspired by "the programmers" answer:
const rowSplitChars = this.determineCSVLineBreak(text);
const columnSplitChars = this.determineCSVDelimiter(text, rowSplitChars);
private determineCSVLineBreak(text: any): string {
try {
const delArray = ["\r\n", "\n", "\r"];
const rnrnArray =
[text.match(/\r/g).length
,text.match(/\n/g).length
,text.match(/\r\n/g).length];
return delArray[this.getMaxIndexInArray(rnrnArray)];
} catch {
this.handleError('Error determining CSV file line break character.');
return '';
}
}
private determineCSVDelimiter(text: any, rowSplitChars: string): string {
const t = text.split(rowSplitChars)[0];
const delArray = [',', ';', '|', ' '];
const countArray =
[t.split(delArray[0]).length
,t.split(delArray[1]).length
,t.split(delArray[2]).length
,t.split(delArray[3]).length];
return delArray[this.getMaxIndexInArray(countArray)];
}
private getMaxIndexInArray(countArray: any[]) {
let max = countArray[0];
let maxIndex = 0;
for (let i = 1; i < countArray.length; i++) {
if (countArray[i] > max) {
maxIndex = i;
max = countArray[i];
}
}
return maxIndex;
}
I have a piece of JavaScript code that I am executing using the node.js interpreter.
for(var i = 1; i < LIMIT; i++) {
var user = {
id: i,
name: "MongoUser [" + i + "]"
};
db.users.save(user, function(err, saved) {
if(err || !saved) {
console.log("Error");
} else {
console.log("Saved");
}
});
}
How can I measure the time taken by these database insert operations? I could compute the difference of date values after and before this piece of code but that would be incorrect because of the asynchronous nature of the code.
Use the Node.js console.time() and console.timeEnd():
var i;
console.time("dbsave");
for(i = 1; i < LIMIT; i++){
db.users.save({id : i, name : "MongoUser [" + i + "]"}, end);
}
end = function(err, saved) {
console.log(( err || !saved )?"Error":"Saved");
if(--i === 1){
console.timeEnd("dbsave");
}
};
There is a method that is designed for this. Check out process.hrtime(); .
So, I basically put this at the top of my app.
var start = process.hrtime();
var elapsed_time = function(note){
var precision = 3; // 3 decimal places
var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time
start = process.hrtime(); // reset the timer
}
Then I use it to see how long functions take. Here's a basic example that prints the contents of a text file called "output.txt":
var debug = true;
http.createServer(function(request, response) {
if(debug) console.log("----------------------------------");
if(debug) elapsed_time("recieved request");
var send_html = function(err, contents) {
if(debug) elapsed_time("start send_html()");
response.writeHead(200, {'Content-Type': 'text/html' } );
response.end(contents);
if(debug) elapsed_time("end send_html()");
}
if(debug) elapsed_time("start readFile()");
fs.readFile('output.txt', send_html);
if(debug) elapsed_time("end readFile()");
}).listen(8080);
Here's a quick test you can run in a terminal (BASH shell):
for i in {1..100}; do echo $i; curl http://localhost:8080/; done
Invoking console.time('label') will record the current time in milliseconds, then later calling console.timeEnd('label') will display the duration from that point.
The time in milliseconds will be automatically printed alongside the label, so you don't have to make a separate call to console.log to print a label:
console.time('test');
//some code
console.timeEnd('test'); //Prints something like that-> test: 11374.004ms
For more information, see Mozilla's developer docs on console.time.
Surprised no one had mentioned yet the new built in libraries:
Available in Node >= 8.5, and should be in Modern Browers
https://developer.mozilla.org/en-US/docs/Web/API/Performance
https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#
Node 8.5 ~ 9.x (Firefox, Chrome)
// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
await delay(1000);
}
performance.mark('A');
(async ()=>{
await doSomeLongRunningProcess();
performance.mark('B');
performance.measure('A to B', 'A', 'B');
const measure = performance.getEntriesByName('A to B')[0];
// firefox appears to only show second precision.
console.log(measure.duration);
// apparently you should clean up...
performance.clearMarks();
performance.clearMeasures();
// Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();
https://repl.it/#CodyGeisler/NodeJsPerformanceHooks
Node 12.x
https://nodejs.org/docs/latest-v12.x/api/perf_hooks.html
const { PerformanceObserver, performance } = require('perf_hooks');
const delay = time => new Promise(res => setTimeout(res, time))
async function doSomeLongRunningProcess() {
await delay(1000);
}
const obs = new PerformanceObserver((items) => {
console.log('PerformanceObserver A to B',items.getEntries()[0].duration);
// apparently you should clean up...
performance.clearMarks();
// performance.clearMeasures(); // Not a function in Node.js 12
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('A');
(async function main(){
try{
await performance.timerify(doSomeLongRunningProcess)();
performance.mark('B');
performance.measure('A to B', 'A', 'B');
}catch(e){
console.log('main() error',e);
}
})();
For anyone want to get time elapsed value instead of console output :
use process.hrtime() as #D.Deriso suggestion, below is my simpler approach :
function functionToBeMeasured() {
var startTime = process.hrtime();
// do some task...
// ......
var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime));
console.log('It takes ' + elapsedSeconds + 'seconds');
}
function parseHrtimeToSeconds(hrtime) {
var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
return seconds;
}
var start = +new Date();
var counter = 0;
for(var i = 1; i < LIMIT; i++){
++counter;
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
if (--counter === 0)
{
var end = +new Date();
console.log("all users saved in " + (end-start) + " milliseconds");
}
});
}
Old question but for a simple API and light-weight solution; you can use perfy which uses high-resolution real time (process.hrtime) internally.
var perfy = require('perfy');
function end(label) {
return function (err, saved) {
console.log(err ? 'Error' : 'Saved');
console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds
};
}
for (var i = 1; i < LIMIT; i++) {
var label = 'db-save-' + i;
perfy.start(label); // <——— start and mark time
db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label));
}
Note that each time perfy.end(label) is called, that instance is auto-destroyed.
Disclosure: Wrote this module, inspired by D.Deriso's answer. Docs here.
You could also try exectimer. It gives you feedback like:
var t = require("exectimer");
var myFunction() {
var tick = new t.tick("myFunction");
tick.start();
// do some processing and end this tick
tick.stop();
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.myFunction.min()); // minimal tick duration
console.log(t.timers.myFunction.max()); // maximal tick duration
console.log(t.timers.myFunction.mean()); // mean tick duration
console.log(t.timers.myFunction.median()); // median tick duration
[edit] There is an even simpler way now to use exectime. Your code could be wrapped like this:
var t = require('exectimer'),
Tick = t.Tick;
for(var i = 1; i < LIMIT; i++){
Tick.wrap(function saveUsers(done) {
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
done();
});
});
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.saveUsers.min()); // minimal tick duration
console.log(t.timers.saveUsers.max()); // maximal tick duration
console.log(t.timers.saveUsers.mean()); // mean tick duration
console.log(t.timers.saveUsers.median()); // median tick duration
You can use a wrapper function to easily report the execution time of any existing function.
A wrapper is a used to extend an existing function to do something before and after the existing function's execution - and is a convenient way to compose logic.
Here is an example of using the withDurationReporting wrapper:
// without duration reporting
const doSomethingThatMayTakeAWhile = async (someArg: string, anotherArg: number) => {
/** your logic goes here */
}
// with duration reporting
const doSomethingThatMayTakeAWhileWithReporting = withDurationReporting(
'doSomethingThatMayTakeAWhile',
doSomethingThatMayTakeAWhile
);
// note: you can define the function with duration reporting directly, too
const doSomethingThatMayTakeAWhile = withDurationReporting(
'doSomethingThatMayTakeAWhile',
async (someArg: string, anotherArg: number) => {
/** your logic goes here */
}
)
And here is the wrapper itself:
import { hrtime } from 'process';
const roundToHundredths = (num: number) => Math.round(num * 100) / 100; // https://stackoverflow.com/a/14968691/3068233
/**
* a wrapper which reports how long it took to execute a function, after the function completes
*/
export const withDurationReporting = <R extends any, T extends (...args: any[]) => Promise<R>>(
title: string,
logic: T,
options: {
reportingThresholdSeconds: number;
logMethod: (message: string, metadata?: Record<string, any>) => void;
} = {
reportingThresholdSeconds: 1, // report on anything that takes more than 1 second, by default
logMethod: console.log, // log with `console.log` by default
},
) => {
return (async (...args: Parameters<T>): Promise<R> => {
const startTimeInNanoseconds = hrtime.bigint();
const result = await logic(...args);
const endTimeInNanoseconds = hrtime.bigint();
const durationInNanoseconds = endTimeInNanoseconds - startTimeInNanoseconds;
const durationInSeconds = roundToHundredths(Number(durationInNanoseconds) / 1e9); // https://stackoverflow.com/a/53970656/3068233
if (durationInSeconds >= options.reportingThresholdSeconds)
options.logMethod(`${title} took ${durationInSeconds} seconds to execute`, { title, durationInSeconds });
return result;
}) as T;
};
I designed a simple method for this, using console.time() & console.timeEnd():
measure function definition
function measureRunningTime(func,...args){
const varToString = varObj => Object.keys(varObj)[0]
const displayName = func.name || varToString({ func })
console.time(displayName)
func(...args)
console.timeEnd(displayName)
}
To use it, pass a function without arguments, with arguments binded, or with arguments as the following parameters.
Examples:
let's say I want to check the running time of the simplest searching algorithm - SimpleSearch:
measured function definition (your code here)
const simpleSearch = (array = [1,2,3] ,item = 3) => {
for(let i = 0; i< array.length; i++){
if (array[i] === item) return i;
}
return -1
}
implementation without arguments
measureRunningTime(simpleSearch)
//Prints something like that-> simpleSearch: 0.04ms
implementation with arguments using .bind()
const array = [1,2,3]
const item = 3
measureRunningTime(simpleSearch.bind(null, array, item))
//Prints something like that-> bound simpleSearch: 0.04ms
implementation with arguments without using .bind()
const array = [1,2,3]
const item = 3
measureRunningTime(simpleSearch, array, item)
//Prints something like that-> simpleSearch: 0.04ms
-> Take notice!! this implementation is far from perfect - for example there is no error handling - but it can be used to check the running times of simple algorithms,
Moreover , I'm not an experienced programmer so take everything with a grain of salt 🧂 👌
I had same issue while moving from AWS to Azure
For express & aws, you can already use, existing time() and timeEnd()
For Azure, use this:
https://github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_azure_aws.js
These time() and timeEnd() use the existing hrtime() function, which give high-resolution real time.
Hope this helps.
I need this to be cumulative, and to measure different stuff.
Built these functions:
function startMeasuring(key) {
measureTimers[key] = process.hrtime();
}
function stopMeasuring(key) {
if (!measures[key]) {
measures[key] = 0;
}
let hrtime = process.hrtime(measureTimers[key]);
measures[key] += hrtime[0] + hrtime[1] / 1e9;
measureTimers[key] = null;
}
Usage:
startMeasuring("first Promise");
startMeasuring("first and second Promises");
await new Promise((resolve) => {
setTimeout(resolve, 1400);
});
stopMeasuring("first Promise");
stopMeasuring("first and second Promises");
startMeasuring("first and second Promises");
await new Promise((resolve) => {
setTimeout(resolve, 600);
});
stopMeasuring("first and second Promises");
console.log("Measure Results", measures);
/*
Measusre Results {
setting: 0.00002375,
'first Promise': 1.409392916,
'first and second Promise': 2.015160376
}
*/
I'd like to use console.log() to log messages without appending a new line after each call to console.log(). Is this possible?
No, it's not possible. You'll have to keep a string and concatenate if you want it all in one line, or put your output elsewhere (say, another window).
In NodeJS you can use process.stdout.write and you can add '\n' if you want.
console.log(msg) is equivalent to process.stdout.write(msg + '\n').
Yes, it's possible (check out the demo below) -- by implementing your own virtual console on top of the native browser console, then syncing it to the real one.
This is much easier than it sounds:
maintain a display buffer (e.g. an array of strings representing one line each)
call console.clear() before writing to erase any previous contents
call console.log() (or warn, error, etc) to fill the console with the contents from your display buffer
Actually, I've been doing this for some time now. A short, rudimentary implementation of the idea would be something along the following lines, but still capable of animating the console contents:
// =================================================
// Rudimentary implementation of a virtual console.
// =================================================
var virtualConsole = {
lines: [],
currentLine: 0,
log: function (msg, appendToCurrentLine) {
if (!appendToCurrentLine) virtualConsole.currentLine++;
if (appendToCurrentLine && virtualConsole.lines[virtualConsole.currentLine]) {
virtualConsole.lines[virtualConsole.currentLine] += msg;
} else {
virtualConsole.lines[virtualConsole.currentLine] = msg;
}
console.clear();
virtualConsole.lines.forEach(function (line) {
console.log(line);
});
},
clear: function () {
console.clear();
virtualConsole.currentLine = 0;
}
}
// =================================================
// Little demo to demonstrate how it looks.
// =================================================
// Write an initial console entry.
virtualConsole.log("Loading");
// Append to last line a few times.
var loadIndicatorInterval = setInterval(function () {
virtualConsole.log(".", true); // <- Append.
}, 500);
// Write a new line.
setTimeout(function () {
clearInterval(loadIndicatorInterval);
virtualConsole.log("Finished."); // <- New line.
}, 8000);
It sure has its drawbacks when mixing with direct console interaction, and can definitely look ugly -- but it certainly has its valid uses, which you couldn't achieve without it.
You can put as many things in arguments as you'd like:
console.log('hi','these','words','will','be','separated','by','spaces',window,document)
You'll get all that output on one line with the object references inline and you can then drop down their inspectors from there.
The short answer is no.
But
If your use-case involves attempting to log perpetually changing data while avoiding console-bloat, then one way to achieve this (in certain browsers) would be to use console.clear() before each output.
function writeSingleLine (msg) {
console.clear();
console.log(msg);
}
writeSingleLine('this');
setTimeout( function () { writeSingleLine('is'); }, 1000);
setTimeout( function () { writeSingleLine('a'); }, 2000);
setTimeout( function () { writeSingleLine('hack'); }, 3000);
Note that this would probably break any other logging functionality that was taking place within your application.
Disclaimer: I would class this as a hack.
collect your output in an array and then use join function with a preferred separator
function echo(name, num){
var ar= [];
for(var i =0;i<num;i++){
ar.push(name);
}
console.log(ar.join(', '));
}
echo("apple",3)
check also Array.prototype.join() for mode details
var elements = ['Fire', 'Wind', 'Rain'];
console.log(elements.join());
// expected output: Fire,Wind,Rain
console.log(elements.join(''));
// expected output: FireWindRain
console.log(elements.join('-'));
// expected output: Fire-Wind-Rain
If your only purpose to stop printing on many lines, One way is to group the values if you don't want them to fill your complete console
P.S.:- See you browser console for output
let arr = new Array(10).fill(0)
console.groupCollapsed('index')
arr.forEach((val,index) => {
console.log(index)
})
console.groupEnd()
console.group
console.groupCollapsed
Something about #shennan idea:
function init(poolSize) {
var pool = [];
console._log = console.log;
console.log = function log() {
pool.push(arguments);
while (pool.length > poolSize) pool.shift();
draw();
}
console.toLast = function toLast() {
while (pool.length > poolSize) pool.shift();
var last = pool.pop() || [];
for (var a = 0; a < arguments.length; a++) {
last[last.length++] = arguments[a];
}
pool.push(last);
draw();
}
function draw() {
console.clear();
for(var i = 0; i < pool.length; i++)
console._log.apply(console, pool[i]);
}
}
function restore() {
console.log = console._log;
delete console._log;
delete console.toLast;
}
init(3);
console.log(1);
console.log(2);
console.log(3);
console.log(4); // 1 will disappeared here
console.toLast(5); // 5 will go to row with 4
restore();
A simple solution using buffered output. Works with deno and should work with node.js. (built for porting pascal console programs to javascript)
const write = (function(){
let buffer = '';
return function (text='\n') {
buffer += text;
let chunks = buffer.split('\n');
buffer = chunks.pop();
for (let chunk of chunks)
{console.log(chunk);}
}
})();
function writeln(text) { write(text + '\n'); }
To flush the buffer, you should call write() at the end of program.
If you mix this with console.log calls, you may get garbage output.
if you want for example console log array elements without a newline you can do like this
const arr = [1,2,3,4,5];
Array.prototype.log = (sep='') => {
let res = '';
for(let j=0; j<this.lengthl j++){
res += this[j];
res += sep;
}
console.log(res);
}
// console loging
arr.log(sep=' '); // result is: 1 2 3 4 5
Useful for debugging or learning what long chained maps are actually doing.
let myConsole = (function(){
let the_log_buffer=[[]], the_count=0, the_single_line=false;
const THE_CONSOLE=console, LINE_DIVIDER=' ~ ', ONE_LINE='ONE_LINE',
PARAMETER_SEPARATOR= ', ', NEW_LINE = Symbol();
const start = (line_type='NOT_ONE_LINE') => {
the_log_buffer=[[]];
the_count=0;
the_single_line = line_type == ONE_LINE;
console = myConsole;
}
const stop = () => {
isNewline();
console = THE_CONSOLE;
};
const isNewline = a_param => {
if (the_single_line && a_param==NEW_LINE) return;
const buffer_parts = the_log_buffer.map(one_set=> one_set.join(PARAMETER_SEPARATOR))
const buffer_line = buffer_parts.join(LINE_DIVIDER);
if (the_single_line) {
THE_CONSOLE.clear();
}
THE_CONSOLE.log( buffer_line );
the_log_buffer = [[]];
the_count=0;
}
const anObject = an_object => {
if (an_object instanceof Error){
const error_props = [...Object.getOwnPropertyNames(an_object)];
error_props.map( error_key => an_object['_' + error_key] = an_object[error_key] );
}
the_log_buffer[the_count].push(JSON.stringify(an_object));
}
const aScalar = a_scalar => {
if (typeof a_scalar === 'string' && !isNaN(a_scalar)) {
the_log_buffer[the_count].push("'" + a_scalar + "'");
} else {
the_log_buffer[the_count].push(a_scalar);
}
}
const notNewline = a_param => typeof a_param === 'object' ? anObject(a_param):aScalar(a_param);
const checkNewline = a_param => a_param == NEW_LINE ? isNewline(a_param) : notNewline(a_param);
const log = (...parameters_list) => {
the_log_buffer[the_count]=[];
parameters_list.map( checkNewline );
if (the_single_line){
isNewline(undefined);
}else{
const last_log = parameters_list.pop();
if (last_log !== NEW_LINE){
the_count++;
}
}
}
return Object.assign({}, console, {start, stop, log, ONE_LINE, NEW_LINE});
})();
function showConcatLog(){
myConsole.stop();
myConsole.start();
console.log('a');
console.log('bb');
console.dir({i:'not', j:'affected', k:'but not in step'})
console.log('ccc');
console.log([1,2,3,4,5,'6'], {x:8, y:'9'});
console.log("dddd", 1, '2', 3, myConsole.NEW_LINE);
console.log("z", myConsole.NEW_LINE, 8, '7');
console.log(new Error("error test"));
myConsole.stop();
}
myConsole.start(myConsole.ONE_LINE);
var stop_callback = 5;
function myCallback(){
console.log(stop_callback, 'Date.now()', myConsole.NEW_LINE, Date.now());
stop_callback--;
if (stop_callback>0){
window.setTimeout(myCallback, 1000);
}else{
showConcatLog();
}
}
window.setTimeout(myCallback, 1000);
You can use a spread operator to display output in the single line. The new feature of javascript ES6. see below example
for(let i = 1; i<=10; i++){
let arrData = [];
for(let j = 1; j<= 10; j++){
arrData.push(j+"X"+i+"="+(j*i));
}
console.log(...arrData);
}
That will print 1 to 10 table in single line.
// Source code for printing 2d array
window.onload = function () {
var A = [[1, 2], [3, 4]];
Print(A);
}
function Print(A) {
var rows = A.length;
var cols = A[0].length;
var line = "";
for (var r = 0; r < rows; r++) {
line = "";
for (var c = 0; c < cols; c++) {
line += A[r][c] + " ";
}
console.log(line);
}
}