Replacing all of the repeated characters in javascript - javascript

function duplicateEncode(word){
var i;
var j;
for(i = 0; i < word.length; i++) {
for(j = i + 1; j < word.length; j++) {
if (word[i] == word[j]) {
word = word.replace(/word[i]/gi, ')');
}
else word = word.replace(/word[i]/gi, '(');
};
};
return word;
}
I need to get ( if character is not repeated in the word and this ) if it is and this code doesnt work it just gives me the word back that I type in.

You are not using regex properly. Here is one possible solution based off of your original code. As you know, Strings are immutable in Javascript so we need to rebuild the string every time using your approach.
function duplicateEncode(word){
for(i = 0; i < word.length; i++) {
if (word[i] == word[i+1]) {
word = word.substring(0,i) + ')' + word.substring(i+1);
}
else {
word = word.substring(0,i) + '(' + word.substring(i+1);
}
}
return word;
}
To avoid rebuilding the string we can store the characters in an array and then join them at the end for a performance boost for large strings.
function duplicateEncode(word){
const newWordArr = [];
for(i = 0; i < word.length; i++) {
if (word[i] == word[i+1]) {
newWordArr.push(')');
}
else {
newWordArr.push('(');
}
}
return newWordArr.join('');
}

Related

Duplicate a character depending on its position in a string

I would like to duplicate every single letter in my string and uppercasing the first letter.
Like this case:
accum("abcd") -> "A-Bb-Ccc-Dddd".
However, it alters the first letter of the string. I think I should add another iterator called "j". But I don't know how to do it.
Precisely, the only task remaining in my code is to move on to the next letter while saving the changes made for the first letter.
function accum(s) {
var i = 0;
while ( i<s.length){
for (var j =i; j<i ; j++) {
s=s[j].toUpperCase()+s[j].repeat(j)+"-";
i+=1;
}
}
return s.slice(0,s.length-1);
}
Try this:
function accum(s) {
let newString = '';
for(let i = 0; i < s.length; i++) {
newString += s[i].toUpperCase() + s[i].repeat(i) + "-";
}
return newString.slice(0, newString.length - 1);
}
I guess you don't need two repetition loops at all (either you can keep the for or the while, i kept the for).
Your fundamental mistake was in this line: s=s[j].toUpperCase()+s[j].repeat(j)+"-"; where you replaced s with the new string instead of concatenating it (s += instead of s = ). Which would be wrong anyway because you are replacing the original string. You need another empty string to keep the changes separated from the original one.
Do this:
function accum(s) {
accumStr = '';
for (var i=0; i < s.length; i++) {
for (var j = 0; j <= i; j++) {
accumStr += j !== 0 ? s[i] : s[i].toUpperCase();
}
}
return accumStr;
}
console.log(accum('abcd')) //ABbCccDddd
Try this:
function accum(s) {
let strArr = s.split('');
let res = [];
for (let i in strArr) {
res.push(strArr[i].repeat(parseInt(i)+1));
res[i] = res[i].charAt(0).toUpperCase() + res[i].slice(1);
}
return res.join('-');
}
console.log(accum('abcd'))
try to use reduce method
const accum = (str) => {
return [...str].reduce(
(acc, item, index, arr) =>
acc +
item.toUpperCase() +
item.repeat(index) +
(index < arr.length - 1 ? "-" : ""),
""
);
};
console.log(accum("abcd")); //A-Bb-Ccc-Dddd

Troubleshooting Algorithm

Im working on an algorithm to return the provided string with the first letter of each word capitalized. While leaving the rest of the word in lower case. Looking for some insight to why this code isn't working. Thanks.
function titleCase(str) {
let result = "";
let words = str.split(" ");
for(let i = 0; i <= words.length; i++){
let word = words[i];
for(let j = 0; j <= word.length; j++){
if(j === 0){
result += word[j].toUpperCase();
} else{
result += word[j].toLowerCase();
}
}
return result += " "
}
return result.slice(0, result.length - 1)
}
There are three errors in your program, that are stopping it from working:
You need to change i <= words.length to i < words.length (or i <= words.length - 1), since indexes start from 0 in javascript like most
programming languages.
You need to change j <= word.length to j < word.length (or j <= word.length - 1), same reason as above.
You need to not return prematurely, and need to change return result += " " to just result += " ".
Also although it does not stop your function from working you could simplify your return line by utilizing trimEnd.
function titleCase(str) {
let result = "";
let words = str.split(" ");
for (let i = 0; i < words.length; i++) {
let word = words[i];
for (let j = 0; j < word.length; j++) {
if (j === 0) {
result += word[j].toUpperCase();
} else {
result += word[j].toLowerCase();
}
}
result += " "
}
return result.trimEnd();
}
console.log(titleCase("The quick brown fox jumps over the lazy dog"));

Javascript - Fastest search for a word in array of string (not full match also)

I am coding search on a webpage which searchs all files, which the webpage consists of.
I iterate through every file and save all words to array of strings.
For example: var array = ["these","are","some","random","words","on","a","webpage"]
The search engine works this way: e.g. user type "s" and if any word from array contains this letter, the word is displayed as a result. In this case the results would be: "these", "some", "words"
The problem is that I have like 30 files in which I search and in each file there is on average 500 words so the search is slow.
letter search (e.g. "s") ~ 4 seconds
letter search (e.g. "se") ~ 2.1 seconds
letter search (e.g. "sea") ~ 1.9 seconds
letter search (e.g. "sear") ~ 1.7 seconds...
I iterate through the array with for-cycle and I think that is the biggest problem. So what is the fastest way to find if searched word is in array of strings and compare also not full matches?
EDIT:
On the webpage it looks like this e.g.:
Searched word: "sear"
Results:
Intro (name of page; clickable url link)
...you can search in this page... (sentence with words around the searched word)
Code explanation:
iterating through files
remove html characters and other special characters and save words from file to array of strings
compare words from file with words which user search for
save sentence with the searched word to a sentence variable
save sentence to an object (this object is later iterated in .html file and the sentences are displayed at webpage)
words typed by user which are going to be searched are in variable words
Here is my code.
var searchIndexPromise;
var searchAppModule = angular.module("searchApp", []);
searchAppModule.run(function($rootScope, $http){
var globalSearch = $rootScope.globalSearch = {
query: "",
results: [],
open: function(){
window.location.href = "#!/51_00_Search";
globalSearch.search(globalSearch.query);
},
search: function(find) {
if(!searchIndexPromise) searchIndexPromise = $http.get("searchIndex.json").then(function(response){
return response.data;
});
console.log("searching", find);
searchIndexPromise.then(function(searchIndex){
var temp = [];
globalSearch.results = [];
var words = find.split(' ');
if (words < 1) {
return;
}
for (var key in searchIndex) {
for (var option in searchIndex[key]) {
for(var i=0; i < words.length; i++) {
if (key.includes(words[i].toLowerCase())) {
var name = searchIndex[key][option].name;
var page = searchIndex[key][option].page;
var word = words[i];
var count = 0;
for (var j = 0; j < temp.length; j++) {
if (temp[j].name == name && temp[j].word == word) {
break;
}
count++;
}
if (count == temp.length) {
temp.push({ name : name, page : page, word : word });
}
}
}
}
}
if (words.length < 2) {
globalSearch.results = temp;
}
else {
for (var i = 0; i < temp.length; i++) {
var count = 0;
var compare = temp[i];
for (var j = 0; j < temp.length; j++) {
if (compare.name == temp[j].name) {
if (globalSearch.results.indexOf(temp[j]) == -1) {
count++;
}
}
}
if (count == words.length) {
globalSearch.results.push(temp[i]);
}
}
}
//sentences
const pagesLoad = require("./pages.js");
globalSearch.pages = [];
for (var result in globalSearch.results) {
var page = globalSearch.results[result].page.substring(3);
if ((page + ".html" in pagesLoad)) {
var nameOfPage = page + ".html";
}
if ((page + ".md" in pagesLoad)) {
var nameOfPage = page + ".md";
}
var regex = /(<([^>]+)>)|\n|\#|\(|\)|\*|\-|[^\w\s!?]|\n| +(?= )/ig, data = pagesLoad[nameOfPage].src.replace(regex, " ");
var string = data.split(" ");
string = string.filter(Boolean);
let lowerString = string.map((item) => {
return item.toLowerCase();
});
//this part is slowing down the search
for (var i = 0; i < lowerString.length; i++) {
for (var j = 0; j < words.length; j++) {
if (lowerString[i].includes(words[j].toLowerCase())) {
var sentence = "...";
for (var k = i - 6; k < i + 6; k++) {
if (lowerString[k] == null) {
continue;
}
sentence = sentence + string[k] + " ";
}
sentence = sentence.slice(0, -1);
sentence += "...";
globalSearch.pages.push({page: globalSearch.results[result].page, sentence: sentence});
}
}
}
}
})
}
};
});

naive string matching algorithm gone wrong

I am trying to implement naive search and I do not get the expected result. Can anyone point out here, what could be the possible error.
function naive(string, str) {
for (let i = 0; i <= string.length - str.length; i++) {
if (string[i] == str[0]) {
let counter = 1
for (let j = 1; j <= str.length; j++) {
if (string[i + j] == str[j]) {
counter++;
console.log(counter)
} else
counter = 0;
}
if (counter == str.length) {
console.log(`${counter} pattern matched at ${i}`)
}
} else
console.log('nothing matched')
}
}
var match_found = false;
function naive(string, str){
for(let i =0; i <= string.length - str.length; i++){
if(string[i] == str[0]){
let counter= 1
for(let j = 1; j < str.length; j++){
if(string[i + j] == str[j]){
counter++;
}else{
break;
}
}
if(counter == str.length){
console.log('Pattern matched at ' + i);
match_found = true;// can break; here if you wish to, else it will give you all matches present
}
}
}
if(match_found === false){
console.log(str + ' not found in ' + string);
}
}
naive('abcdgggabcdggg','ggg');
You increment the counter when there is a match, but you need to break the loop where there is a mismatch.
Your inner for loop condition needs to have j < str.length instead of j <= str.length, because index starts from 0.
else console.log('nothing matched'). You can't just instantly decide that. If a string index doesn't match, you need to still keep looking for the rest of the indexes.
Best way to go about it is to maintain a boolean flag for it as shown in the above code.
You don't need to do all that iteration and comparison by yourself. Here's a simpler version of your function:
function naive(string, str) {
var counter = 0,
i = string.indexOf(str, 0); //find first occurance of str in string
while(i !== -1){
++counter; //we have a match, count one up
console.log(`counter %i, index %i`, counter, i);
i = string.indexOf(str, i+1); //find next occurance
}
return counter;
}
console.log("result", naive("lorem upsum", "m"));

Get JS to recognize white spaces .split()

I wrote this function to log a new string from the given string where the letters should be the following one in the alphabet and all of the vowels would be uppercase.
Now I have the issue of not being able to split the string the way I want it. Right now the words are being split into separate characters in an array when I'd really like the string to be split on the white spaces. Could anybody explain why this is happening?
And when I put a space between the "" in the split method I just get all the characters and "undefined" where the white spaces should be. Thanks for your help!
function replace(str) {
var newStr = [];
var vowels = 'aeiou';
var alpha = [ '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'
];
str = str.split("");
newStr.length = str.length;
for(var i = 0; i < alpha.length; i++) {
for(var j = 0; j < str.length; j++) {
if(alpha[i] === str[j]) {
newStr[j] = (alpha[i + 1]);
}
}
}
for(var k = 0; k < vowels.length; k++) {
for(var x =0; x < newStr.length; x++){
if(vowels[k] === newStr[x]) {
newStr[x] = vowels[k].toUpperCase("");
}
}
}
return newStr;
}
console.log(replace("today is great"));
str = str.split(" ");
This splits your string up into ["today", "is", "great"].
When you get to
if(alpha[i] === str[j]) {
you never get inside the if block because you are comparing "a" to "today" or "a" to "is", etc. You'll need to break your string up even more to get this done I think.
I propose something like:
function replace(str) {
var alpha = ['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'],
vowels = 'aeiou',
newStr = [],
i, j, k;
// split everything into words
str = str.split(' ');
for (i = 0; i < str.length; i++) {
// split everything into letters
str[i] = str[i].split('');
// make sure newStr has a similarly construction to str
newStr[i] = [];
for (j = 0; j < str[i].length; j++) {
for (k = 0; k < alpha.length; k++) {
if (alpha[k] === str[i][j]) {
// subsitute each letter
newStr[i][j] = alpha[k + 1];
}
}
}
}
for (i = 0; i < newStr.length; i++) {
// join newStr up to be an array of words instead of an array of an array of letters
newStr[i] = newStr[i].join('');
for (k = 0; k < vowels.length; k++) {
// replace each vowel with the uppercase version
newStr[i] = newStr[i].replace(vowels[k], vowels[k].toUpperCase());
}
}
return newStr;
}
If you actually want to see "UpEbz jt hsfbU" instead of ["UpEbz", "jt", "hsfbU"], just change return newStr to return newStr.join(' ');
To split string on whitespace try:
str = str.split(/\s+/);

Categories