First of all: I'm a bit into JavaScript but not much.
Today I saw these code:
if (stringToSearch[i].charCodeAt(0) === codeToSearch) {
The charCodeAt() method of String is used for to compare the current char with the searched char.
The full code of the function here:
function getOccurences (stringToSearch, charToSearch) {
var ret = 0;
var codeToSearch = 0;
var i;
stringToSearch = stringToSearch.toUpperCase();
codeToSearch = charToSearch.toUpperCase().charCodeAt(0);
for (i = 0; i < stringToSearch.length; i++) {
if (stringToSearch[i].charCodeAt(0) === codeToSearch) {
ret++;
}
}
return ret;
}
I would have compared the char directly. Without using charCodeAt().
Just ...
stringToSearch[i] === charToSeach
As far as I know the computer compares just numbers anyway. Translates the characters to their UTF-codes. Subtracts these numbers against each other and then checks if the result has become zero.
So therefore my question:
Does the usage of charCodeAt() makes any sense?
Are there a benefit to favor the direct charCode-comparison over the character-comparison.
My intuition is to say there's a performance hit when you go through type-conversion and function-calling hoops like that.
That said, you'll likely eke out more performance out of the code by delegating to the native string methods, with something like:
function countCaseInsensitiveOccurrences(haystack, char) {
haystack = haystack.toUpperCase();
char = char.toUpperCase()[0];
var count = 0, pos = -1;
while ((pos = haystack.indexOf(char, pos + 1)) !== -1) {
count++;
}
return count;
}
charCode benefits when we have to increment/decrement the characters.
eg. if we have charCode('a') in variable x, then we can increment it using x++.
But if we had saved 'a' then we cannot perform arithmetic operations.
So charCodeAt(number) is used when you need to increment/decrement the characters.
Related
I'm making a calculator for a site project of mine where you can type your entire expression before resolving, for example: 2+3*4 would return 14, 22-4 would return 18, 20+5! would return 140, and so on.
And that works for simple expressions like the ones I showed, but when I add brackets the code breaks.
So a simple expression like (2+3)! that should return 120 actually returns 10 or 2+3!.
my original ideia to make even the basic 2+3! work was to separate the string in math simbols and the rest. so it would separate in this case it would separate it into 2, + and 3!; where it would find the symbol and resolve just that part. And that's why it solves 10 instead of not working.
But after trying to solve I couldn't make the code work except in a extremely specific situation, so I decided to redo the code and post this here in case someone could help me out.
This is the function that I'm currently using to prepare my string for evaluation:
function sepOperFat(){
//2+3! it's working
//1+(2-(2+2)+3)! want that to work in the end
var value = document.calculator.ans.value;
var operandoPos = ['0'];
var operandoInPos = [''];
var paraResolver = [];
for(i = 0; i <= value.length; i++){
//check if value[i] is equal to +, -, ×, ÷, * & /
if(value[i] == '+' || value[i] == '-' || value[i] == '×' || value[i] == '÷' || value[i] == '*' || value[i] == '/'){
operandoPos.push(i);
operandoInPos.push(value[i]);
}
}
paraResolver.push(value.slice(operandoPos[0], operandoPos[1]));
for(var total = 1; total <= operandoPos.length; total++){
paraResolver.push(value.slice(operandoPos[total] + 1, operandoPos[total + 1]));
}
document.calculator.ans.value = '';
for(var total = 0; total <= paraResolver.length - 2; total++){
if(paraResolver[total].includes('!')){
document.calculator.ans.value += "factorial(" + paraResolver[total] + ")";
}else{
document.calculator.ans.value += paraResolver[total];
}
document.calculator.ans.value += operandoInPos[total + 1];
}
}
document.calculator.ans.value is the name of the string where i have the expression.
operandoPos is the position on the string where a symbol is at.
operandoInPos is the symbol (I maybe could have used value.charAt(operandoPos) for that too).
paraResolver is the number that I will be solving (like 3).
factorial( is the name of my function responsible for making the number factorial.
the function doesn't have a return because I still want to solve inside the document.calculator.ans.value.
to resolve the equation I'm using document.calculator.ans.value = Function('"use strict"; return '+ document.calculator.ans.value)(); that activates when I press a button.
And yeah, that's it. I just want a function capable of knowing the difference between (2+3)! and 2+(3)! so it can return factorial(2+3) instead of (2+factorial(3)).
Thank you for your help.
Your biggest problem is going to be that order of operations says parentheses need to be evaluated first. This might mean your code has to change considerably to support whatever comes out of your parentheses parsing.
I don't think you want all of that handled for you, but an approach you can take to sorting out the parenthesis part is something like this:
function parseParentheses(input) {
let openParenCount = 0;
let myOpenParenIndex = 0;
let myEndParenIndex = 0;
const result = [];
for (let i = 0; i < input.length; i++) {
if (input[i] === '(') {
if (openParenCount === 0) {
myOpenParenIndex=i;
// checking if anything exists before this set of parentheses
if (i !== myEndParenIndex) {
result.push(input.substring(myEndParenIndex, i));
}
}
openParenCount++;
}
if (input[i] === ')') {
openParenCount--;
if (openParenCount === 0) {
myEndParenIndex=i+1;
// recurse the contents of the parentheses to search for nested ones
result.push(parseParentheses(input.substring(myOpenParenIndex+1, i)));
}
}
}
// capture anything after the last parentheses
if (input.length > myEndParenIndex) {
result.push(input.substring(myEndParenIndex, input.length));
}
return result;
}
// tests
console.log(JSON.stringify(parseParentheses('1!+20'))) // ["1!+20"]
console.log(JSON.stringify(parseParentheses('1-(2+2)!'))) // ["1-",["2+2"],"!"]
console.log(JSON.stringify(parseParentheses('(1-3)*(2+5)'))) // [["1-3"],"*",["2+5"]]
console.log(JSON.stringify(parseParentheses('1+(2-(3+4))'))) // ["1+",["2-",["3+4"]]]
this will wrap your input in an array, and essentially group anything wrapped in brackets into nested arrays.
I can further explain what's happening here, but you're not likely to want this specific code so much as the general idea of how you might approach unwrapping parenthesis.
It's worth noting, the code I've provided is barely functional and has no error handling, and will behave poorly if something like 1 - (2 + 3 or 1 - )2+3( is provided.
"Write a JavaScript function to find longest substring in a given a string without repeating characters."
Here's what I tried, but it doesn't print anything
function sort(names) {
let string = "";
let namestring = names.split("");
for(let i = 0; i < namestring.length; i++) {
for(let j = 0; j < string.length; j++) {
if(string[j] != namestring[i]) {
string = string + namestring[i];
}
}
}
return string;
}
console.log(sort("google.com"));
What's wrong?
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i]))
break;
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
It's o(n^2) complexity but try this(may be o(n^3) if contains function take o(n) complexity)
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i])) // if contains not work then
break; //use includes like in snippet
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
What are you expecting the answer to be here? Should it be "ogle.com" or "gle.com"? If the first, the below should get you there, if the latter, update the tested = name.charAt(i) in the else to tested = "".
So a few things to note, though you're more than welcome to do as you wish:
1) the function name. This isn't doing a "sort" as far as I can tell, so if this is for your use (or any reuse. Basically, anything more than a one off homework assignment), you may want to rename it to something you'd actually remember (even the example I give is probably not completely best as "pick longest substring" is non-descriptive criteria).
2) variable naming. string and namestring may mean something to you here, but considering we're trying to find the longest substring (with the no double characters) in a string, I felt it was better to have the one we're checking against (tested) and the one we're storing to return later (longest). It helps make sense as you're reading through the code as you know when you are done with a checked string (tested), you want to compare if it is greater than the current longest substring (longest) and if it is bigger, you want it to be the new longest. This will save you a ton of headache to name variables to things that'll help when designing your function as you can get it as close to requirements written down as possible without trying to do some form of substitution or worse, forgetting which variable holds what.
I don't know what you want the result to be in the event that tested length is the same as longest length. Currently I have it set to retain, if you want the most recent, update the check to >=.
Beyond that, I just iterate over the string, setting to the currently tested string. Once double characters are met, I then see if what I just generated (tested) is larger than the current longest and if it is, it is now the longest. Once I finish looping across the string, I have to do the current vs longest check/set again as otherwise, it'd make the final tested meaningless (it went outside the loop before another double character situation was hit).
function pickLongestSubstring(name) {
let tested = "";
let longest = "";
for (let i = 0; i < name.length; i++) {
if (tested.length == 0 || tested.charAt(tested.length - 1) != name.charAt(i)) {
tested += name.charAt(i);
}
else {
if (tested.length > longest.length) {
longest = tested;
tested = "";
}
}
}
if (tested.length > longest.length) {
longest = tested;
}
return longest;
}
console.log(pickLongestSubstring("google.com"))
console.log(pickLongestSubstring("example.com"))
This is a recursive loop that should get the longest string. Uses sort to determine longest string. Works, even if multiple instances of same repeat char.
function longestWithoutRepeat(testString, returnString){
var returnString = returnString || "";
for(var i = 0; i < testString.length; i++) {
if(i > 0){
if(testString[i] == testString[i-1]) {
var testStringArray = testString.split(testString[i] + testString[i-1]);
testStringArray.sort(function(firstString, nextString){ return nextString.length - firstString.length})
returnString = testStringArray[0];
longestWithoutRepeat(testStringArray[0], returnString);
}
} else {
returnString = testString
}
}
return returnString;
}
console.log(longestWithoutRepeat("oolong"));
console.log(longestWithoutRepeat("google.com"));
console.log(longestWithoutRepeat("diddlyougotoofarout"));
I'm starting to learn javascript and I basically needed a countup that adds an x value to a number(which is 0) every 1 second. I adapted a few codes I found on the web and came up with this:
var d=0;
var delay=1000;
var y=750;
function countup() {
document.getElementById('burgers').firstChild.nodeValue=y+d;
d+=y;
setTimeout(function(){countup()},delay);
}
if(window.addEventListener){
window.addEventListener('load',countup,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',countup);
}
}
There's probably residual code there but it works as intended.
Now my next step was to divide the resultant string every 3 digits using a "," - basically 1050503 would become 1,050,503.
This is what I found and adapted from my research:
"number".match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
I just can't find a way to incorporate this code into the other. What should I use to replace the "number" part of this code?
The answer might be obvious but I've tried everything I knew without sucess.
Thanks in advance!
To use your match statement, you need to convert your number to a String.
Let's say you have 1234567.
var a = 1234567;
a = a + ""; //converts to string
alert(a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(","));
If you wish, you can wrap this into a function:
function baz(a) {
a = a + "";
return a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
}
Usage is baz(1234); and will return a string for y our.
While I do commend you for using a pattern matching algorithm, this would probably be easier to, practically speaking, implement using a basic string parsing function, as it doesn't look anywhere as intimidating from just looking at the match statement.
function foo(bar) {
charbar = (""+bar).split(""); //convert to a String
output = "";
for(x = 0; x < charbar.length; x++) { //work backwards from end of string
i = charbar.length - 1 - x; //our index
output = charbar[i] + output; //pre-pend the character to the output
if(x%3 == 2 && i > 0) { //every 3rd, we stick in a comma, except if it is not the leftmost digit
output = ',' + output;
}
}
return output;
}
Usage is basically foo(1234); which yields 1,234.
I have a large array have almost 10000 strings, I want to find all the common part (which is longer than 3 chars)in these strings and get the occurrence of these parts.
I implement with my simple method with javascript, but it really cost a lot of time, even I did some optimization on that, for a short array of 1000 strings, it cost about 8s for Firefox and 12s for Chrome.
So I wonder if there are any related technology or algorithm, as I think it is really a common problem which could be raised in many application.
Build an array of all possible substrings, sort them and then look for blocks of consecutive equal strings.
The implementation below looks for suffixes of a certain length and imposes a minimal number of matches. It is not clear what you want exactly, but you need some constraints. It is easy to look for the longest common suffixes, but if you just want common suffixes, what does that mean? Are 20 occurences of a 4-character string better than 10 occurrences of a 5-character string?
Also, note that the code below does not check for overlapping strings. If you look for matches of length 4 and have 30 words with "green" in it, the result will contain both "gree" and "reen".
It might not be what you want, but it should be easy to adapt. And it's reasonably fast. On 10,000 randomly generated strings with about 30 chars each, it takes less than a second to find common substrings of length 10 and maybe 4 seconds for 1000,000 strings.
Anyway, here goes:
/*
* Return an array of all substrings of the given length
* that occur at least mincount times in all the strings in
* the input array strings.
*/
function substrings(strings, length, mincount) {
var suffix = [];
var res = [];
for (var i = 0; i < strings.length; i++) {
var s = strings[i];
for (var j = 0; j < s.length - length + 1; j++) {
suffix.push(s.substr(j, length));
}
}
suffix.sort();
suffix.push("");
var last = "";
var count = 1;
for (var i = 0; i < suffix.length; i++) {
var s = suffix[i];
if (s == last) {
count++;
} else {
if (count >= mincount) res.push(last);
count = 1;
}
last = s;
}
return res;
}
Check out Crossfilter http://square.github.io/crossfilter/ It will do whatever kind of map-reduce you want. Javascript can be very slow for searching through big messes, though. Depending on your constraints, and how that 10,000 strings will grow over time, you might think of an RDMS, like MySQL, since they are designed for this type of thing.
I had a slightly different issue where I needed to find the common prefixes across each word not just common substrings which could be in the middle or end of the word. This function will return the common prefixes across a set of words.
function findCommonPrefixes (words, min) {
const result = new Set();
for (const word of words) {
let partial = word.toLowerCase();
do {
const otherWords = words.filter(w => w !== word).map(w => w.toLowerCase());
for (const word of otherWords) {
if (word.includes(partial)) {
result.add(partial);
partial = '';
break;
}
}
if (partial) {
partial = partial.slice(0, (partial.length - 1))
}
} while (partial.length && partial.length >= min)
}
return Array.from(result);
}
I'm trying to build a function that adds up all the numbers within a string... for example, 'dlsjf3diw62' would end up being 65.
I tried to be clever and put together a recursive function:
function NumberAddition(str) {
var numbers='1234567890';
var check=[];
str=str.split[''];
function recursive(str,check) {
if (str.length==0)
return check;
else if (numbers.indexOf(str[0])>=0)
{
for (i=0;i<str.length;i++){
if (numbers.indexOf(str[i])<0)
check.push(str.slice(0,i));
str=str.slice(i);
return recursive(str,check);
}
}
else
str.shift();
return recursive(str,check);
}
You'll see that I'm trying to get my numbers returned as an array in the array named check. Unfortunately, I have a maximum call stack size exceeded, and I'm not sure why! The recursion does have a base case!! It ends once str no longer has any contents. Why wouldn't this work? Is there something I'm missing?
-Will
You can achieve the same thing with a far easier solution, using regular expressions, as follows:
var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits
Then, to sum the numbers, you can do this:
var checkSum = 0;
for (var i = 0; i < check.length; i++) {
checkSum += parseInt(check[i]);
}
Or, slightly more compact:
var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);
The reason your recursion doesn't work is the case where you do enter the for loop, because you've found a digit, but the digits continue to the end of the string. If that happens, the return inside the for loop never happens, and the loop ends. After that, the .shift() does not happen, because it's in that else branch, so you return re-process the same string.
You shouldn't solve this particular problem that way, but the code makes a good example of the anti-pattern of having return statements inside if bodies followed by else. Your code would be clearer (and would work) if it looked like this:
function recursive(str, check) {
if (str.length == 0)
return check;
if (numbers.indexOf(str[0]) >= 0) {
// Find the end of the string of digits, or
// the end of the whole thing
for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);
check.push(str.slice(0, i));
str = str.slice(i);
return recursive(str, check);
}
// A non-digit character
str.shift();
return recursive(str, check);
}
In that version, there are no else clauses, because the two if clauses always involve a return. The for loop is changed to simply find the right value of "i" for the subsequent slicing.
edit — one thing this doesn't fix is the fact that you're pushing arrays into your "check" list. That is, the substring "62" would be pushed as the array ["6", "2"]. That's not a huge problem; it's solved with the addition of a .join() in the right place.