algorithm to compress a string - javascript

I want to write a function to compress the characters of a string such as 'bbbab' would be converted to 'b3ab' and I'm getting stuck
it's only printing "b3"
here's the code so far
let string = 'bbbab';
let letters = string.split("");
let currentAlphabetLetter = letters[0];
let count = 0;
let newString = [];
string.split("").forEach(letter => {
if (letter === currentAlphabetLetter) {
count++;
} else {
if (count > 0) {
newString.push(`${currentAlphabetLetter}${count}`);
} else {
newString.push(`${letter}`);
}
count = 0;
currentAlphabetLetter = letter;
}
})
console.log(newString);

When you start a new letter, you need to set count to 1, otherwise you're not counting the first occurrence of the character.
This isn't a problem at the very beginning of the string, because you process the first letter twice: you extract it with let currentAlphabetLetter = letters[0]; and then process it again on the first iteration of the forEach. To make the beginning of the string the same as other occurrences, you should iterate over the substring starting with the 2nd character.
And rather than pushing onto an array, you should append to a string.
When count is 1 you need to append currentAlphabetLetter, not letter.
let string = 'bbbab';
let letters = string.split("");
let currentAlphabetLetter = letters[0];
let count = 1;
let newString = "";
string.substr(1).split("").forEach(letter => {
if (letter === currentAlphabetLetter) {
count++;
} else {
if (count > 1) {
newString += `${currentAlphabetLetter}${count}`;
} else {
newString += `${currentAlphabetLetter}`;
}
count = 1;
currentAlphabetLetter = letter;
}
});
// Process the last letter
if (count > 1) {
newString += `${currentAlphabetLetter}${count}`;
} else {
newString += `${currentAlphabetLetter}`;
}
console.log(newString);

You may do as follows;
var str = 'bbbabccc',
res = [...str].reduce((r,c,i) => (r[r.length-1][0] === c || !i) ? (r[r.length-1] += c, r)
: r.concat(c), [""])
.reduce((r,s) => r + s[0] + (s.length-1 ? s.length : ""), "");
console.log(res);
We have two .reduce()s cascaded here but first it's good to know that [...str] turns into ["b", "b", "b", "a", "b", "c", "c", "c"].
The first .reduce() will reduce it to an array of strings such as ["bbb", "a", "b", "ccc"].
The second .reduce() will further reduce it to the result. The inner mechanics of each reducers are for you to solve.
However, as hint, keep in mind that the comma operator , as in (r[r.length-1] += c, r) takes the last element of r array (accumulator here) adds c to the end of it and returns r.

Like this should work for you
let string = 'bbbab';
let newString = [];
if (string.length < 2) { console.log(string); }
else {
let letters = string.split("");
let prev = letters[0];
let count = 1;
for( var i = 1; i < letters.length; i++) {
if (letters[i] !== prev) {
count > 1 ? newString.push(`${prev}${count}`) : newString.push(`${prev}`);
count = 1;
} else {
count++;
}
prev = letters[i];
}
/* last element push */
count > 1 ? newString.push(`${prev}${count}`) : newString.push(`${prev}`);
console.log(newString.join(""));
}

Related

Replace substring using for loop

I'm trying to replace a substring with the word 'denied'. For example: if the original string is "abcdefg" and sub-string to replace is "bcd", expected output is "aDENIEDefg".
I can't use .replace or anything else, just .substring
function replacer (variable, replace) {
for (let a = variable.length - 1; a >=0; a--) {
for (let b = replace.length - 1; b >= 0; b--) {
if (replace[b] === variable[a]) {
}
}
}
}
I have no clue what to do next.
Here is my code to just remove characters from a string.
let stringToReturn = original;
for (let a = toDelete.length - 1; a >= 0; a--) {
for (let b = original.length - 1; b >= 0; b--) {
if (original[b] === toDelete[a]) {
stringToReturn = stringToReturn.substring(0, b) + stringToReturn.substring(b + 1, stringToReturn.length);
} else {
continue;
}
}
}
alert(stringToReturn);
}
But this time I need not to just remove one characters, but find a sub-string to replace with DENIED. I apologize for the code style.
If you know the length of the substring you're trying to replace, then you can just iterate the string and examine all possible substrings of this length, as you were looking through a "window":
function replace(full, partial, placeholder) {
for (let i = 0; i <= full.length - partial.length; i++) {
const current = full.substring(i, i + partial.length);
if (current === partial) {
const prefix = full.substring(0, i);
const suffix = full.substring(i + partial.length);
return `${prefix}${placeholder}${suffix}`;
}
}
}
const ans = replace('abcdefghij', 'def', 'DENIED');
console.log(ans);
If you want to replace all occurrences, just don't return the value after the first match:
function replaceAll(full, partial, placeholder) {
let tmp = full;
for (let i = 0; i <= tmp.length - partial.length; i++) {
const current = tmp.substring(i, i + partial.length);
if (current === partial) {
const prefix = tmp.substring(0, i);
const suffix = tmp.substring(i + partial.length);
tmp = `${prefix}${placeholder}${suffix}`;
i += placeholder.length;
}
}
return tmp;
}
const ans = replaceAll('abcdefghijdef', 'def', 'DENIED');
console.log(ans);
Since you didn't specify whether you want to do a full replace or a singular, I've modified this to allow for a boolean parameter, this boolean says whether to do a singular or full replace.
const replaceword = "DENIED";
const testword = "abcdef";
const testword2 = "abcdefdexyz";
const testword3 = "hello I don't have the sub";
//function takes a word parameter - the word to do a replace on
//and sub parameter of what to replace
//and replacement parameter of what to replace the substring with
//replaceall is a boolean as to whether to do a full replace or singular
function replace(word, sub, replacement, replaceall){
replaceall = replaceall || false; //default to singular replace
//Get the first index of the sub to replace
const startOfReplace = word.indexOf(sub);
//get the ending index of where the substring to be replaced ends
const endOfReplace = startOfReplace + sub.length - 1;
//variable to hold new word after replace
let replacedWord = "";
//If the substring is found do the replacement with the given replacement word
if(startOfReplace > -1){
for(let i = 0; i < word.length; i++){
if(i == startOfReplace){
replacedWord += replacement;
}else if(i >= startOfReplace && i <= endOfReplace){
continue;
}else{
replacedWord += word[i];
}
}
}else{ //set the return to the passed in word as no replacement can be done
replacedWord = word;
return replacedWord;
}
if(replaceall) //if boolean is true, recursively call function to replace all occurrences
//recursive call if the word has the sub more than once
return replace(replacedWord, sub, replacement);
else
return replacedWord; //else do the singular replacement
}
console.log(replace(testword, "de", replaceword));
console.log(replace(testword2, "de", replaceword, true));
console.log(replace(testword3, "de", replaceword));
const source = "abcdefg";
const target = "bcd";
const replacer = "DENIED";
const replace = (source, target, replacer) => {
const position = source.indexOf(target);
if(position === -1) return source;
let output = source.substr(0, position)
output += replacer
output += source.substr(position + target.length);
return output
}
const replaceAll = (source, target, replacer) => {
let output = source;
do{
output = replace(output, target, replacer)
}
while(output !== replace(output, target, replacer))
return output;
}
console.log(replace(source, target, replacer))
and for sure best solution, easiest to understand, clean and elegant is :
const replaceAll = (source, target, replacer) => {
return source.split(target).join(replacer)
}

Character with longest consecutive repetition

i think i have wirtten the correct code for the problem only one thing and it that i return the first longest sequence how can i alter that to return the last maximum sequence?
an example from codewars editor :
for input '00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'
Expected: ['c', 19], instead got: ['0', 19]
here is my code:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i)
}
else {
temp = s.charAt(i);
arr.push(count)
count = 1;
}
if(i==s.length-1)
arr.push(count);
}
if(arr.length>0)
{
var Max=arr[0]
for(var i=0;i<arr.length;i++)
{
if(Max<=arr[i])
Max=arr[i];
}
}
else var Max=0;
var mindex=arr.indexOf(Max);
return [s.charAt(mindex),Max]
}
I think this would be easier with a regular expression. Match any character, then backreference that character as many times as you can.
Then, you'll have an array of all the sequential sequences, eg ['000', 'aaaaa']. Map each string to its length and pass into Math.max, and you'll know how long the longest sequence is.
Lastly, filter the sequences by those which have that much length, and return the last item in the filtered array:
function longestRepetition(s) {
const repeatedChars = s.match(/(.)\1*/g);
const longestLength = Math.max(...repeatedChars.map(str => str.length));
const longestChars = repeatedChars.filter(str => str.length === longestLength);
return [longestChars.pop(), longestLength];
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The issue in your code is that minindex is an index in your arr, but that index has nothing to do with s. So s.charAt(minindex) makes no sense. You should maintain for which character you had found the count. For instance you could push in arr both the count and the corresponding character (as a subarray with two values). Then the rest of your code would only need little modification to make it work.
Applying this idea to your code without changing anything else, we get this:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i) // Not necessary: was already equal
}
else {
arr.push([temp, count]); // <--- pair, BEFORE changing temp
temp = s.charAt(i);
count = 1;
}
if(i==s.length-1)
arr.push([temp, count]); // <---
}
if(arr.length>0)
{
var Max=arr[0]; // <-- Max is now a pair of char & count
for(var i=0;i<arr.length;i++)
{
if(Max[1]<arr[i][1]) // Comparison changed to just less-than
Max=arr[i];
}
}
else Max=[null, 0]; // Must be a pair here also
return Max; // Just return the pair
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
But you can do the same with less code:
function longestRepetition(s) {
let result = [null, 0]; // pair of character and count
for (var i = 0; i < s.length; null) {
let start = i++;
while (i < s.length && s[i] === s[start]) i++; // Find end of series
if (i - start > result[1]) result = [s[start], i - start];
}
return result;
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The solution below answers the question with O(n) runtime:
function longestRepetition(s) {
let count = s.length > 0 ? 1 : 0
let char = s.length > 0 ? s[0] : ''
for (let string_i = 0; string_i < s.length - 1; string_i += 1) {
// keep track of current_char
let current_char = s[string_i]
let next_char = s[string_i + 1]
// while the next char is same as current_char
let tracker = 1
while (current_char === next_char) {
// add one to tracker
tracker += 1
string_i += 1
next_char = s[string_i + 1]
}
// if tracker greater than count
if (tracker > count) {
// returned char = current char
// count =tracker
count = tracker;
char = current_char;
}
}
return [char, count]
}
console.log(longestRepetition("bbbaaabaaaa"))//, ["a",4]

Replace a letter with its alphabet position

This looked fairly straightforward to me when I started, but for some reason I'm getting an empty array everytime I try to run the result on codewars. I'm hoping you can help me identify what the problem is.
function alphabetPosition(text) {
text.split(' ').join('');
var chari = "";
var arr = [];
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for(var i = 0; i < text.len; i++){
chari = text.charAt(i).toLowerCase();
if(alphabet.indexOf(chari) > -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World"));
My idea is to get the text from the parameter then strip out the spaces. I made a variable for my empty array and make an alphabet string that I can later search through. In the for loop, i make each character lowercase, and if the character is found in the alphabet string, its position gets pushed into the array (arr). I appreciate your time.
The Kata works with this code. Try with this one:
function alphabetPosition(text) {
var result = "";
for (var i = 0; i < text.length; i++) {
var code = text.toUpperCase().charCodeAt(i)
if (code > 64 && code < 91) result += (code - 64) + " ";
}
return result.slice(0, result.length - 1);
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
You need the String#length property
text.length
instead of text.len.
function alphabetPosition(text) {
var chari,
arr = [],
alphabet = "abcdefghijklmnopqrstuvwxyz",
i;
for (var i = 0; i < text.length; i++){
chari = text[i].toLowerCase();
if (alphabet.indexOf(chari) !== -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World!!1"));
A solution with ES6
function alphabetPosition(text) {
return [...text].map(a => parseInt(a, 36) - 10).filter(a => a >= 0);
}
console.log(alphabetPosition("Hello World!!1"));
First : deleting space
Second : mapping each char with its alphabet rank
Third : test with the string Happy new year
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
var alphabetPosition = text =>
text.split('').map(x => alphabet.indexOf(x) + 1);
console.log(alphabetPosition("happy new year"));
function alphabetPosition(text) {
const words = text.toLowerCase().replace(/[^a-z]/g,"");
return [...words].map(v=> v.charCodeAt() - 96);
}
First we take the text and transform it into lowercase to get rid of the capital letters using text.toLowerCase() and then we do .replace(/[^a-z]/g,"") to replace all the non a-z characters with nothing.
The next step is to spread the string out into an array using [...words] and then mapping it to get the ascii character code of each a-z character.
Since a = 97 and b = 98 etc we will subtract 96 so that we get a = 1 and b = 2 etc (the position of the letters in the alphabet)
You can make it even easier, by making use of the acii code. Because a = ascii code 97, b = 98 etc. And there is a javascript function String.charCodeAt( n ) which returns the ascii code at a specific function. You only have to alter the offset for capitals (if you want to support them).
function alphabetPosition( text ) {
var positions = [];
for ( var i = 0; i < text.length; i++ ) {
var charCode = text.charCodeAt( i );
if ( charCode >= 97 && charCode <= 122 ) {
positions.push( charCode - 96 );
} else if ( charCode >= 65 && charCode <= 90 ) { // get rid of this if you don't care about capitals
positions.push( charCode - 64 );
}
}
return positions;
}
var positions = alphabetPosition( 'Hello World' );
console.log(positions);
Checkout this working fiddle
This example will return based on a 0 based array, and uses lambda expressions with filter. I recycle the original byte array created by splitting the text passed to the method.
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase());
}
return bytes.filter(n => { if(n > -1) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
For a 1 based array result Kata Codewars Friendly
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase()) + 1;
}
return bytes.filter(n => { if(n > 0) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
You can also use .charCodeAt function:
function alphabetPosition(text) {
start = "a".charCodeAt(0);
end = "z".charCodeAt(0);
res = [];
for (var i = 0; i < text.length; i++) {
index = text.charAt(i).toLowerCase().charCodeAt(0);
if (index >= start && index <= end) {
res.push(index - start +1); // +1 assuming a is 1 instead of 0
} else {
res.push(0); // Or do w/e you like with non-characters
}
}
return res;
}
console.log(alphabetPosition("Hello World"));
You may do something like this;
var alpha = [].reduce.call("abcdefghijklmnopqrstuvwxyz0123456789 .,!",(p,c,i) => (p[c] = i,p),{}),
str = "Happy 2017 whatever..!",
coded = [].map.call(str, c => alpha[c.toLowerCase()]);
console.log(coded);
change len to length:
(var i = 0; i < text.len; i++)
// change to
(var i = 0; i < text.length; i++)
Here is a much shorter version that does the same:
function alphabetPosition(text){
return text.split('').map(function(character){ return character.charCodeAt(0) - 'a'.charCodeAt(0) + 1; })
}
console.log(alphabetPosition("Hello World"));
This was my solution on CodeWars. Works perfectly ;)
let alphabetPosition = (text) => {
let str = Array.from(text.toLowerCase().replace(/[^a-z]/g,''));
let arr = [];
for (let i = 0; i < str.length; i++) {
arr.push(str[i].charCodeAt() - 96);
}
return arr.join(' ');
}
my answer
function alphabetPosition(text) {
if (text.match(/[a-z]/gi)) { // if text is not emtpty
let justAlphabet = text.match(/[a-z]/gi).join("").toLowerCase(); //first extract characters other than letters
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let a = []; // Create an empty array
for (let i = 0; i < justAlphabet.length; i++) {
a.push(alphabet.indexOf(justAlphabet[i]) + 1); //and characters index number push in this array
}
return a.join(" ");
} else {
return "";
}
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
this one should work
const lineNumberHandler = (arr) => {
const alphabet = 'abcdefghijklmnopqrstuwxyz';
return arr.map((el) => `${alphabet.indexOf(el) + 1}:${el}`);
}
This may solve the issue too:
function alphabetPosition(text) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const textWithoutSpaces = text.replace(/\s/g, '');
const numbers = Array.from(textWithoutSpaces).map((letter) => {
const lowerCaseLetter = letter.toLowerCase();
const charI = alphabet.indexOf(lowerCaseLetter)+1
if(charI) return charI
return null
})
const withoutEmptyValues = numbers.filter(Boolean)
return withoutEmptyValues.join(' ')
}
function alphabetPosition(text) {
const letters = text.split('')
const result = letters.map((l, ix) => {
const code = l.toUpperCase().charCodeAt() - 64
if (l.length && code > 0 && code <= 26) {
return code
}
})
return result.join(' ').replace(/\s+/g, ' ').trim()
}
I like to do "Single Line Responsibility", so in every line you can find only one action.
The return line, delete all multiples spaces.
An optimized version of it.
function alphabetPosition(text) {
let split = text.split("");
split = split.filter((el) => /^[a-zA-Z]+$/.test(el));
let str = "";
split.forEach(
(el) => (str += el.toLowerCase().charCodeAt(0) - "96" + " ")
);
return str.trim();
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
function alphaPosition(test){
//the object assigns the position value to every alphabet property
const lookupAlph = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26}
//converts our text first to lowercase, then removes every non-alphabet
// it proceeds to covert the text to an array,
// then we use the map method to convert it to its position in the alphabet
// the last thing we do is convert our array back to a string using the join method
const alphaPosition = text.toLowerCase()
.replace(/[^a-z]/g, "")
.split("")
.map((a) => lookupAlph[a])
.join(" ")
return alphaPosition;
}

How to ignore spaces in string indexes and start with a capital letter on each word in a sentence

Basically, I have this code, where I want to change a given string to wEiRd CaSe, alternate between indexes, for example:
Starting from index 0 I want the letter to be capital, and then when the index got to an odd number, like 1, 3, 5, etc... I want to change it to uppercase.
So:
Stackoverflow should be StAcKoVeRfLoW, But I also want to work with strings, strings like this
This is a test should be: ThIs Is A TeSt
But my function returns : ThIs iS A TeSt
Here's my code:
"use strict";
var weirdCase = function(string) {
var characters = string.split("");
characters.forEach(function(value, index, characters) {
// If the index is even
if (index % 2 == 0) {
characters[index] = value.toUpperCase();
} else {
characters[index] = value.toLowerCase();
}
});
return characters.join("");
}
My question might be a bit misleading, I wanted to be wEiRd Case but also the first letter of the words to be capital, So I did this:
function toWeirdCase(string){
return string.split(' ').map(function(word){
return word.split('').map(function(letter, index){
return index % 2 == 0 ? letter.toUpperCase() : letter.toLowerCase()
}).join('');
}).join(' ');
}
Hope this helps someone
You can add another variable charIndex which you increase manually only if the value is no space. charIndex will represent the indexes for your string like it has no spaces in it.
"use strict";
var weirdCase = function(string) {
var characters = string.split("");
var charIndex = 0;
characters.forEach(function(value, index, characters) {
//Exclude spaces
if (value === " ") {
return;
}
// If the index is even
if (charIndex % 2 == 0) {
characters[index] = value.toUpperCase();
} else {
characters[index] = value.toLowerCase();
}
//Increment charIndex
charIndex += 1;
});
return characters.join("");
}
Should be as simple as this:
function WeIrDcAsE(string) {
let isUpperCase = true;
let result = '';
for (let character of string) {
if (isUpperCase) {
result += character.toUpperCase();
} else {
result += character.toLowerCase();
}
if (character.match(/[a-zA-Z]/)) {
isUpperCase = !isUpperCase;
} else {
isUpperCase = true;
}
}
return result;
}
console.log(WeIrDcAsE("This is a test!"));
In a much more simpler way...
a = "This is a test"
b = a.split('')
counter = 0
c = b.map(function(c) {
if (c === ' ') return c
if ((counter % 2) === 0) {
counter++
return c.toUpperCase()
}
counter++
return c.toLowerCase()
})
console.log(c.join(''))
This code can be simplified a lot, I think.
var weirdCase = function(str){
var upper = false;
for (var i = 0; i < str.length; i++){
if (str[i] != ' '){
if (upper){
str[i] = character.toUpperCase();
}else{
str[i] = character.toLowerCase();
}
upper = !upper;
}
}
I would do as follows;
var str = "this is a test",
result = str.split(" ")
.map(s => [].reduce
.call(s, (p,c,i) => p += i & 1 ? c.toLowerCase()
: c.toUpperCase(),""))
.join(" ");
console.log(result);
var string= 'Stackoverflow';
for (var i=0; i<string.length; i+=2)
string= string.substr(0,i) + string[i].toUpperCase() + string.substr(i+1);
Nev er mid, scratch this: I need to read more carefully, sorry.

Find the characters in a string which are not duplicated

I have to make a function in JavaScript that removes all duplicated letters in a string. So far I've been able to do this: If I have the word "anaconda" it shows me as a result "anaconda" when it should show "cod". Here is my code:
function find_unique_characters( string ){
var unique='';
for(var i=0; i<string.length; i++){
if(unique.indexOf(string[i])==-1){
unique += string[i];
}
}
return unique;
}
console.log(find_unique_characters('baraban'));
We can also now clean things up using filter method:
function removeDuplicateCharacters(string) {
return string
.split('')
.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
.join('');
}
console.log(removeDuplicateCharacters('baraban'));
Working example:
function find_unique_characters(str) {
var unique = '';
for (var i = 0; i < str.length; i++) {
if (str.lastIndexOf(str[i]) == str.indexOf(str[i])) {
unique += str[i];
}
}
return unique;
}
console.log(find_unique_characters('baraban'));
console.log(find_unique_characters('anaconda'));
If you only want to return characters that appear occur once in a string, check if their last occurrence is at the same position as their first occurrence.
Your code was returning all characters in the string at least once, instead of only returning characters that occur no more than once. but obviously you know that already, otherwise there wouldn't be a question ;-)
Just wanted to add my solution for fun:
function removeDoubles(string) {
var mapping = {};
var newString = '';
for (var i = 0; i < string.length; i++) {
if (!(string[i] in mapping)) {
newString += string[i];
mapping[string[i]] = true;
}
}
return newString;
}
With lodash:
_.uniq('baraban').join(''); // returns 'barn'
You can put character as parameter which want to remove as unique like this
function find_unique_characters(str, char){
return [...new Set(str.split(char))].join(char);
}
function find_unique_characters(str, char){
return [...new Set(str.split(char))].join(char);
}
let result = find_unique_characters("aaaha ok yet?", "a");
console.log(result);
//One simple way to remove redundecy of Char in String
var char = "aaavsvvssff"; //Input string
var rst=char.charAt(0);
for(var i=1;i<char.length;i++){
var isExist = rst.search(char.charAt(i));
isExist >=0 ?0:(rst += char.charAt(i) );
}
console.log(JSON.stringify(rst)); //output string : avsf
For strings (in one line)
removeDuplicatesStr = str => [...new Set(str)].join('');
For arrays (in one line)
removeDuplicatesArr = arr => [...new Set(arr)]
Using Set:
removeDuplicates = str => [...new Set(str)].join('');
Thanks to David comment below.
DEMO
function find_unique_characters( string ){
unique=[];
while(string.length>0){
var char = string.charAt(0);
var re = new RegExp(char,"g");
if (string.match(re).length===1) unique.push(char);
string=string.replace(re,"");
}
return unique.join("");
}
console.log(find_unique_characters('baraban')); // rn
console.log(find_unique_characters('anaconda')); //cod
​
var str = 'anaconda'.split('');
var rmDup = str.filter(function(val, i, str){
return str.lastIndexOf(val) === str.indexOf(val);
});
console.log(rmDup); //prints ["c", "o", "d"]
Please verify here: https://jsfiddle.net/jmgy8eg9/1/
Using Set() and destructuring twice is shorter:
const str = 'aaaaaaaabbbbbbbbbbbbbcdeeeeefggggg';
const unique = [...new Set([...str])].join('');
console.log(unique);
Yet another way to remove all letters that appear more than once:
function find_unique_characters( string ) {
var mapping = {};
for(var i = 0; i < string.length; i++) {
var letter = string[i].toString();
mapping[letter] = mapping[letter] + 1 || 1;
}
var unique = '';
for (var letter in mapping) {
if (mapping[letter] === 1)
unique += letter;
}
return unique;
}
Live test case.
Explanation: you loop once over all the characters in the string, mapping each character to the amount of times it occurred in the string. Then you iterate over the items (letters that appeared in the string) and pick only those which appeared only once.
function removeDup(str) {
var arOut = [];
for (var i=0; i < str.length; i++) {
var c = str.charAt(i);
if (c === '_') continue;
if (str.indexOf(c, i+1) === -1) {
arOut.push(c);
}
else {
var rx = new RegExp(c, "g");
str = str.replace(rx, '_');
}
}
return arOut.join('');
}
I have FF/Chrome, on which this works:
var h={};
"anaconda".split("").
map(function(c){h[c] |= 0; h[c]++; return c}).
filter(function(c){return h[c] == 1}).
join("")
Which you can reuse if you write a function like:
function nonRepeaters(s) {
var h={};
return s.split("").
map(function(c){h[c] |= 0; h[c]++; return c}).
filter(function(c){return h[c] == 1}).
join("");
}
For older browsers that lack map, filter etc, I'm guessing that it could be emulated by jQuery or prototype...
This code worked for me on removing duplicate(repeated) characters from a string (even if its words separated by space)
Link: Working Sample JSFiddle
/* This assumes you have trim the string and checked if it empty */
function RemoveDuplicateChars(str) {
var curr_index = 0;
var curr_char;
var strSplit;
var found_first;
while (curr_char != '') {
curr_char = str.charAt(curr_index);
/* Ignore spaces */
if (curr_char == ' ') {
curr_index++;
continue;
}
strSplit = str.split('');
found_first = false;
for (var i=0;i<strSplit.length;i++) {
if(str.charAt(i) == curr_char && !found_first)
found_first = true;
else if (str.charAt(i) == curr_char && found_first) {
/* Remove it from the string */
str = setCharAt(str,i,'');
}
}
curr_index++;
}
return str;
}
function setCharAt(str,index,chr) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
Here's what I used - haven't tested it for spaces or special characters, but should work fine for pure strings:
function uniquereduce(instring){
outstring = ''
instringarray = instring.split('')
used = {}
for (var i = 0; i < instringarray.length; i++) {
if(!used[instringarray[i]]){
used[instringarray[i]] = true
outstring += instringarray[i]
}
}
return outstring
}
Just came across a similar issue (finding the duplicates). Essentially, use a hash to keep track of the character occurrence counts, and build a new string with the "one-hit wonders":
function oneHitWonders(input) {
var a = input.split('');
var l = a.length;
var i = 0;
var h = {};
var r = "";
while (i < l) {
h[a[i]] = (h[a[i]] || 0) + 1;
i += 1;
}
for (var c in h) {
if (h[c] === 1) {
r += c;
}
}
return r;
}
Usage:
var a = "anaconda";
var b = oneHitWonders(a); // b === "cod"
Try this code, it works :)
var str="anaconda";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){
return obj;
}
}
).join("");
//output: "cod"
This should work using Regex ;
NOTE: Actually, i dont know how this regex works ,but i knew its 'shorthand' ,
so,i would have Explain to you better about meaning of this /(.+)(?=.*?\1)/g;.
this regex only return to me the duplicated character in an array ,so i looped through it to got the length of the repeated characters .but this does not work for a special characters like "#" "_" "-", but its give you expected result ; including those special characters if any
function removeDuplicates(str){
var REPEATED_CHARS_REGEX = /(.+)(?=.*?\1)/g;
var res = str.match(REPEATED_CHARS_REGEX);
var word = res.slice(0,1);
var raw = res.slice(1);
var together = new String (word+raw);
var fer = together.toString();
var length = fer.length;
// my sorted duplicate;
var result = '';
for(var i = 0; i < str.length; i++) {
if(result.indexOf(str[i]) < 0) {
result += str[i];
}
}
return {uniques: result,duplicates: length};
} removeDuplicates('anaconda')
The regular expression /([a-zA-Z])\1+$/ is looking for:
([a-zA-Z]]) - A letter which it captures in the first group; then
\1+ - immediately following it one or more copies of that letter; then
$ - the end of the string.
Changing it to /([a-zA-Z]).*?\1/ instead searches for:
([a-zA-Z]) - A letter which it captures in the first group; then
.*? - zero or more characters (the ? denotes as few as possible); until
\1 - it finds a repeat of the first matched character.
I have 3 loopless, one-line approaches to this.
Approach 1 - removes duplicates, and preserves original character order:
var str = "anaconda";
var newstr = str.replace(new RegExp("[^"+str.split("").sort().join("").replace(/(.)\1+/g, "").replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")+"]","g"),"");
//cod
Approach 2 - removes duplicates but does NOT preserve character order, but may be faster than Approach 1 because it uses less Regular Expressions:
var str = "anaconda";
var newstr = str.split("").sort().join("").replace(/(.)\1+/g, "");
//cdo
Approach 3 - removes duplicates, but keeps the unique values (also does not preserve character order):
var str = "anaconda";
var newstr = str.split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
//acdno
function removeduplicate(str) {
let map = new Map();
// n
for (let i = 0; i < str.length; i++) {
if (map.has(str[i])) {
map.set(str[i], map.get(str[i]) + 1);
} else {
map.set(str[i], 1);
}
}
let res = '';
for (let i = 0; i < str.length; i++) {
if (map.get(str[i]) === 1) {
res += str[i];
}
}
// o (2n) - > O(n)
// space o(n)
return res;
}
If you want your function to just return you a unique set of characters in your argument, this piece of code might come in handy.
Here, you can also check for non-unique values which are being recorded in 'nonUnique' titled array:
function remDups(str){
if(!str.length)
return '';
var obj = {};
var unique = [];
var notUnique = [];
for(var i = 0; i < str.length; i++){
obj[str[i]] = (obj[str[i]] || 0) + 1;
}
Object.keys(obj).filter(function(el,ind){
if(obj[el] === 1){
unique+=el;
}
else if(obj[el] > 1){
notUnique+=el;
}
});
return unique;
}
console.log(remDups('anaconda')); //prints 'cod'
If you want to return the set of characters with their just one-time occurrences in the passed string, following piece of code might come in handy:
function remDups(str){
if(!str.length)
return '';
var s = str.split('');
var obj = {};
for(var i = 0; i < s.length; i++){
obj[s[i]] = (obj[s[i]] || 0) + 1;
}
return Object.keys(obj).join('');
}
console.log(remDups('anaconda')); //prints 'ancod'
function removeDuplicates(str) {
var result = "";
var freq = {};
for(i=0;i<str.length;i++){
let char = str[i];
if(freq[char]) {
freq[char]++;
} else {
freq[char] =1
result +=char;
}
}
return result;
}
console.log(("anaconda").split('').sort().join('').replace(/(.)\1+/g, ""));
By this, you can do it in one line.
output: 'cdo'
function removeDuplicates(string){
return string.split('').filter((item, pos, self)=> self.indexOf(item) == pos).join('');
}
the filter will remove all characters has seen before using the index of item and position of the current element
Method 1 : one Simple way with just includes JS- function
var data = 'sssssddddddddddfffffff';
var ary = [];
var item = '';
for (const index in data) {
if (!ary.includes(data[index])) {
ary[index] = data[index];
item += data[index];
}
}
console.log(item);
Method 2 : Yes we can make this possible without using JavaScript function :
var name = 'sssssddddddddddfffffff';
let i = 0;
let newarry = [];
for (let singlestr of name) {
newarry[i] = singlestr;
i++;
}
// now we have new Array and length of string
length = i;
function getLocation(recArray, item, arrayLength) {
firstLaction = -1;
for (let i = 0; i < arrayLength; i++) {
if (recArray[i] === item) {
firstLaction = i;
break;
}
}
return firstLaction;
}
let finalString = '';
for (let b = 0; b < length; b++) {
const result = getLocation(newarry, newarry[b], length);
if (result === b) {
finalString += newarry[b];
}
}
console.log(finalString); // sdf
// Try this way
const str = 'anaconda';
const printUniqueChar = str => {
const strArr = str.split("");
const uniqueArray = strArr.filter(el => {
return strArr.indexOf(el) === strArr.lastIndexOf(el);
});
return uniqueArray.join("");
};
console.log(printUniqueChar(str)); // output-> cod
function RemDuplchar(str)
{
var index={},uniq='',i=0;
while(i<str.length)
{
if (!index[str[i]])
{
index[str[i]]=true;
uniq=uniq+str[i];
}
i++;
}
return uniq;
}
We can remove the duplicate or similar elements in string using for loop and extracting string methods like slice, substring, substr
Example if you want to remove duplicate elements such as aababbafabbb:
var data = document.getElementById("id").value
for(var i = 0; i < data.length; i++)
{
for(var j = i + 1; j < data.length; j++)
{
if(data.charAt(i)==data.charAt(j))
{
data = data.substring(0, j) + data.substring(j + 1);
j = j - 1;
console.log(data);
}
}
}
Please let me know if you want some additional information.

Categories