How to optimize the code? (reverse string) [duplicate] - javascript

This question already has answers here:
Reversing string without affecting any special characters
(7 answers)
Reverse string without reversing special characters using Javascript
(3 answers)
Closed 1 year ago.
The task says : Change the order of words in a sentence but let non-alphanumerical characters stay in the same place e.g: 'Hello, it is world here.' -> "here, world is it Hello."
So far i have created something like this, but i need to optimize it (there are too many loops).
var text = 'Hello, it is world here.';
function reverseFunc(text){
let alpha = text.match(/[a-z0-9]+/gi).reverse();
let nonAlpha = text.match(/[\W_]+/gi);
let result = [];
console.log("Alpha : " + alpha)
console.log("Non alpha : " +nonAlpha)
if(alpha == null || nonAlpha == null) console.log(text)
else if((/[a-z0-9]/i).test(text.split("")[0])){
if (alpha.length == nonAlpha.length) {
for (let i = 0; i < nonAlpha.length; i++) {
result.push(alpha[i], nonAlpha[i]);
}
console.log(result.join(""))
return(result.join(""))
}else{
for (let i = 0; i < alpha.length; i++) {
result.push(alpha[i], nonAlpha[i]);
}
console.log(result.join(""))
return(result.join(""))
}
}else{
if (nonAlpha.length == alpha.length) {
for (let i = 0; i < alpha.length; i++) {
result.push(nonAlpha[i], alpha[i]);
}
console.log(result.join(""))
return(result.join(""))
}else{
for (let i = 0; i < nonAlpha.length; i++) {
result.push(nonAlpha[i], alpha[i]);
}
console.log(result.join(""))
return(result.join(""))
}
}
}
reverseFunc(text)
I also have a problem when the text is only 1 char long e.g ".", or " ". I tried this:
if(alpha == null || nonAlpha == null) console.log(text)
but it seems like it is working only for alphanumeric chars.How could this algorithm be corrected?

Related

How can I extract all contained characters in a String? [duplicate]

I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)

creating a for-loop that prints # signs instead of number values [duplicate]

This question already has answers here:
How to print a half pyramid in javascript
(9 answers)
How to print star pattern in JavaScript in a very simple manner? [closed]
(22 answers)
Closed 1 year ago.
im trying to write a code that outputs lines of '#' signs that increase by one for each value until the input number is reached.
for example, when triangles(3) is called my desired output is:
'#'
'##'
'###'
ive learned how to create this sequence with number values instead of the '#' signs but not sure how to achieve this output displayed above. thanks!
function triangles(num) {
let number = '';
for (let i = 1; i <= num; i++) {
console.log(number += i);
}
}
triangles(5)
this outputs:
'1'
'12'
'123'
'1234'
'12345'
You can use String.prototype.repeat() to repeat the pound (#) character as specified by the current value of i, without needing to declare a new variable to store it:
function triangles(num) {
for (let i = 1; i <= num; i++) {
console.log('#'.repeat(i));
}
}
triangles(5);
function triangles(num) {
let symbol = "#";
for (let i = 1; i <= num; i++) {
console.log(Array(i).fill(symbol).join(""));
}
}
triangles(5);
function triangles(num) {
const c = "#";
for (let i = 1; i <= num; i++) {
console.log(c.repeat(i));
}
}
triangles(5)
You don't have to use console.log to print number += i specifically. If you want to print '#' multiple times, you can use #Terry's answer (which is shorter) or you can use another for loop in your code (this approach could be simpler for beginners).
function triangles(num) {
let number = '';
for (let i = 1; i <= num; i++) {
number++;
let poundkeys = '';
// dont use i again, name it something else (like j or k)
for (let j = 1; j <= number; j++) {
// just like you do number += i, add a pound symbol to poundkeys
poundkeys += '#';
}
// now, log poundkeys
console.log(poundkeys);
}
}
triangles(5);
Also, a quick tip. Generally, it is better not to log number += i. Instead of:
console.log(number += i);
It is encouraged and more readable if you separate them:
number += i;
console.log(number);

How to compress string by JS? [duplicate]

This question already has answers here:
Find the characters in a string which are not duplicated
(29 answers)
Closed 2 years ago.
trying writing func for compressing string(2 equal letter become 1). Don't get how to save the progress of compressing(trying different combo with concat - unsuccessful). Every time my for take full string
CodePen
let pass = '1122333456';
function CompressPass(string) {
for (let i = 0; i < string.length; i++) {
let concisePassword = string.split('');
const item = string[i];
const nextItem = string[i + 1];
console.log(+item, +nextItem);
if (item === nextItem) {
concisePassword.splice(i, 1);
console.log(concisePassword);
} else {
console.log('not equal: ', +item, +nextItem);
}
};
}
CompressPass(pass);
maybe this help you
let pass = '11223322345666600222222';
function CompressPass (string) {
string += '-';
let str = '';
for (let i = 1; i < string.length; i++) {
const nextItem = string[i];
const item = string[i - 1];
if (item != nextItem){
str += item;
}
};
return str;
}
console.log(CompressPass(pass))
you can try 'lz-string' for compressing and de-decompressing string in javascript.
** I used that for compressing local storage data ( as local storage has only a 5MB limit )
** the results may not be visible for shorter strings, but you can try it.
link: https://pieroxy.net/blog/pages/lz-string/index.html
example : (from this above-mentioned link )
<script language="javascript" src="lz-string.js"></script>
<script>
var string = "This is my compression test.";
alert("Size of sample is: " + string.length);
var compressed = LZString.compress(string);
alert("Size of compressed sample is: " + compressed.length);
string = LZString.decompress(compressed);
alert("Sample is: " + string);
</script>

Whats wrong with my palindrome? (javascript)

I have written this js code for palindrome, I know there are better and more efficient palindrome methods online but I want to know why I am unable to get my palindrome function to work properly?
CODE:
var pal = function(str) {
var len = str.length;
for (var i = 0; i < len; i++) {
var comp1 = str.substring(i, i + 1);
for (var j = len; j > 0; j--) {
var comp2 = str.substring(j - 1, j);
}
if (comp1 != comp2) {
console.log("not palindrome")
break;
} else {
console.log('palindrome')
}
}
}
pal('maddog');
OUTPUT :
palindrome
not palindrome
There are lot of better algorithms to check Palindrome. Let use the similar algorithm that you are using.
We basically use two pointers - left and right, and move to middle at the same time. In the original question, left pointer and right pointer doesn't move at the same time.
Pointers should move like this -
a b c b a
^ ^
a b c b a
^ ^
a b c b a
^
var isPalindrome = function (str) {
for (var i = 0, j = str.length-1; i < j; i++ , j--) {
if (str[i] != str[j]) {
return false;
}
}
return true;
}
console.log('maddog : ' + isPalindrome('maddog'));
console.log('abcba : ' + isPalindrome('abcba'));
console.log('deed : ' + isPalindrome('deed'));
console.log('a : ' + isPalindrome('a'));
Try the following code. It works by dividing the string length by 2, and then iterating up, checking mirroring characters against each other:
var pal = function(str){
var len = str.length;
for(var i = 0; i < Math.floor(len/2); i++){
if(str[i] != str[(len-1)-i]){
return false;
}
}
return true;
}
console.log(pal("bunny"));
console.log(pal("amoreroma"));
The inner loop is totally unnecessary. It does the same thing every time -- it loops through the whole string, starting from the end, repeatedly setting comp2 to the character; when it's done, comp2 always contains the first character. So your function just tests whether every character in the string is the same as the first character.
To test if something is a palindrome, you need to compare each character with the corresponding character from the other end of the string. You don't need two loops for this. You also only need to loop through the first half of the string, not the whole string.
Finally, you should only echo Palindrome at the end of the loop. Inside the loop you only know that one character matches, not all of them.
var pal = function(str) {
var len = str.length;
var half = Math.floor(len / 2);
var isPal = true;
for (var i = 0; i < half; i++) {
var comp1 = str[i];
var comp2 = str[len - i - 1];
if (comp1 != comp2) {
console.log("not palindrome")
isPal = false;
break;
}
}
if (isPal) {
console.log('palindrome')
}
}
pal('maddog');
pal('maddam');
You don't really need the nested loops, you can just loop backwards through the string to invert the string and then compare it to the original string. I updated the Snippet to work.
Before, your code was not inverting the string but rather just iterating through the characters and assigning them to the comp1 and comp1 variables. You need to concatenate the strings in order to build the new string backwards comp = comp + str.substring(j-1, j);
var pal = function(str) {
var len = str.length;
var comp = '';
for (var j = len; j > 0; j--) {
comp = comp + str.substring(j - 1, j);
}
if (str !== comp) {
console.log("not palindrome")
return;
}
console.log('palindrome')
}
pal('arepera');

Regex for same word shows first false and then true [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 6 years ago.
I have problem with testing string with regex.
After iterations "aab", "aab", "aba".. here comes the problem when testing string "baa" first time is ok, result is false because regex test is setup to check is there repeating letter inside string, but when testing again "baa" result is now true. Why is this happening?
Here is the code:
//Here are function for swaping letters
String.prototype.swapLetters=function(index) {
var temp = this.split("");
var n = temp[index];
temp[index]=temp[index+1]; temp[index+1]=n;
var str1 = temp.join("");
return str1;
}
function permAlone(str) {
//the function for calculating number of total combinations
function returnFactorial(num){
if(num===0){
return 1;
} else {
return returnFactorial(num-1)*num;
}
}
var combs = returnFactorial(str.length);
var c = 0;
var permutations = 0;
var reg = new RegExp(/(.)\1+/g);
for (var i = 0; i < combs; i++) {
if(c>=str.length-1){
c = 0;
}
str = str.swapLetters(c);
if(!reg.test(str)){
permutations++;
console.log(str);
}
c++;
}
}
permAlone('aab');
Firstly, the condition you have if(!reg.test(str)){} should not have a !(not) in it if you intend to identify a regex match. I am not sure if that is what you wanted, though.
Secondly, I removed the 'global' match flag 'g' so that the regex is basically "reset" to start matching from the beginning of the text before each execution. This is because a single RegExp object when executed multiple times, starts to match the text each time from the last match index. This can give you a detailed explanation for this. Why RegExp with global flag in Javascript give wrong results?.
Try this.
//Here are function for swaping letters
String.prototype.swapLetters=function(index) {
var temp = this.split("");
var n = temp[index];
temp[index]=temp[index+1]; temp[index+1]=n;
var str1 = temp.join("");
return str1;
}
function permAlone(str) {
//the function for calculating number of total combinations
function returnFactorial(num){
if(num===0){
return 1;
} else {
return returnFactorial(num-1)*num;
}
}
var combs = returnFactorial(str.length);
var c = 0;
var permutations = 0;
var reg = new RegExp(/(\w)\1+/);
for (var i = 0; i < combs; i++) {
if(c>=str.length-1){
c = 0;
}
str = str.swapLetters(c);
console.log("case : " + str);
if(reg.test(str)){
permutations++;
console.log(str + " has repeated letters");
}
c++;
}
}
permAlone('aab');

Categories

Resources