Problem when comparing array elements (Javascript) - javascript

Hey I have a small problem. So basically I'm passing string to function as an argument, then converting it to array and I'm trying to compare generated array elements with one another and if they are equal it should return ")" else "(", but there is problem when comparing elements and the values are wrong. Maybe someone could help me.
function duplicateEncode(word) {
let splitString = word.split("");
let newArr = splitString.map((val, index, arr) => {
for (let i = 0; i < splitString.length; i++) {
if (val === arr[i]) {
return ')';
} else {
return '(';
}
}
});
return newArr.join('');
}

Use Javascript's Map object to store if current letter exists or not.
function duplicateEncode(word){
let m = new Map();
let splitString= word.split("");
let coded = "";
splitString.map( s => {
if(!m[s]){
m[s] = true
coded += "("
} else {
coded += ")"
}
})
return coded
}
console.log(duplicateEncode("stack"))

Related

How to remove only one of repeated chars in string using JavaScript

I have a string with repeated chars like : 'CANADA'.
And I am trying to get the string which removed only one of repeated chars :
'CNADA', 'CANDA', 'CANAD'.
I've tried it with subString, but it returned the part of string removed.
Also I've tried it with reduce, but it ended up removing all the repeated chars ('CND').
What is the way of removing only one char at time?
The results can be stored in array. (results = ['CNADA', 'CANDA', 'CANAD'])
Thank you.
You can achieve this by utilizing the second parameter of String#indexOf() which specifies the position from which to start the search. Here in a while loop, and using a Set to remove dulplicates before returning.
function getReplaceOptions(str, char) {
let res = [], i = str.indexOf(char, 0);
while (i !== -1) {
res.push(str.substring(0, i) + str.substring(++i));
i = str.indexOf(char, i)
}
return Array.from(new Set(res))
}
console.log(getReplaceOptions('CANADA', 'A'));
console.log(getReplaceOptions('Mississippi', 's'));
You can first count all the occurrences in the string. Later you can iterate over the script and if the count is greater than 1 you can remove that character.
const theString = 'CANADA'
const letterCount = {}
const resultArr = []
for (var i = 0; i < theString.length; i++) {
const theLetter = theString.charAt(i)
if(letterCount[theLetter]){
letterCount[theLetter] = letterCount[theLetter] + 1
}
else{
letterCount[theLetter] = 1
}
}
console.log(letterCount)
for (var i = 0; i < theString.length; i++) {
const theLetter = theString.charAt(i)
if(letterCount[theLetter] && letterCount[theLetter] > 1){
resultArr.push(theString.substr(0, i) + theString.substr(i + 1))
}
}
console.log(resultArr)
If you want to remove only the first repeating character then you can use matchAll here as:
Just see the browser compatibility before using this
const str = 'CANADA';
const firstRepeatedChar = 'A';
const result = [];
for (let { index } of str.matchAll(firstRepeatedChar)) {
result.push(str.slice(0, index) + str.slice(index + 1));
}
console.log(result);
NOTE: If you want to search for the first repeating character then remove it, then you can do as:
const str = 'CANADA';
let firstRepeatedChar = '';
const set = new Set();
for (let i = 0; i < str.length; ++i) {
if (!set.has(str[i])) {
set.add(str[i]);
} else {
firstRepeatedChar = str[i];
break;
}
}
const result = [];
for (let { index } of str.matchAll(firstRepeatedChar)) {
result.push(str.slice(0, index) + str.slice(index + 1));
}
console.log(result);
You could use some Array magic to remove duplicate characters:
function removeDuplicateCharacters(value) {
// convert string to array and loop through each character
return String(value).split('').filter(function(char, index, all) {
// return false if char found at a different index
return (index === all.indexOf(char));
})
.join(''); // convert back to a string
}
// returns `CAND`
removeDuplicateCharacters('CANADA');
// returns `helo wrd`
removeDuplicateCharacters('hello world');

Running into error creating a Javascript function

I am trying to write a function to change a string written in Snake Case to Camel Case, but running into an error.
function snakeToCamel(string) {
arr = [...string];
for (i of arr) {
if (i === "_") {
let upperCaseLetter = arr[i+1].toUpperCase();
arr.splice(i+1,1,upperCaseLetter);
arr.splice(i,1)
}
};
return arr;
}
The error is here. I can't find what is wrong in the line stated in the error. What is going on?
snakeToCamel("you_dont_know")
snake-to-camel.js:5 Uncaught TypeError: Cannot read property 'toUpperCase' of undefined
at snakeToCamel (snake-to-camel.js:5)
at <anonymous>:1:1
In a for-of loop, the control variable is the array element, not an index. So i in your example is a string. So arr[i+1].toUpperCase(); will do string concatenation and try to look up a property with a name like s1, not 1.
If you want to use the index, you want a for loop or a forEach call (or even map, since that's kind of what you're doing), not a for-of loop.
A couple of other notes:
You need to be sure to declare your variables; right now, your code is falling prey to what I call The Horror of Implicit Globals, creating a global called arr. Add const or let before arr.
You don't put ; after blocks attached to control-flow statements. (You can have them there, because empty statements are allowed, but they're not supposed to be there.)
For example, using a for loop:
function snakeToCamel(string) {
// `const` because we never reassign `arr`
const arr = [...string];
// Traditional `for` so we have the index
for (let i = 0, len = arr.length; i < len; ++i) {
const ch = arr[i];
if (ch === "_") {
if (i === len - 1) {
// Trailing _, just remove it
arr.splice(i, 1);
--i;
--len;
} else {
let upperCaseLetter = arr[i + 1].toUpperCase();
// You can remove the _ and the lowr case letter
// in a single `splice` rather than multiple ones
arr.splice(i, 2, upperCaseLetter);
--i; // Need to do this to allow for multiple `_` in a row
--len;
}
}
};
return arr;
}
console.log(snakeToCamel("one_two__three_"));
Or using map:
function snakeToCamel(string) {
let lastWasUnderscore = false;
const result = [...string]
.map(ch => {
const thisIsUnderscore = ch === "_";
if (lastWasUnderscore && !thisIsUnderscore) {
lastWasUnderscore = false;
return ch.toUpperCase(); // or `.toLocaleUpperCase()`
}
lastWasUnderscore = thisIsUnderscore;
return thisIsUnderscore ? null : ch;
})
.filter(ch => ch !== null);
return result;
}
console.log(snakeToCamel("one_two__three_"));
You were actually fairly close to the solution!
Instead of using a for-of loop I would suggest you use a normal for loop.
This way you can access the index i
function snakeToCamel(string) {
const arr = [...string];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === "_") {
let upperCaseLetter = arr[i+1].toUpperCase();
arr.splice(i+1,1,upperCaseLetter);
arr.splice(i,1)
}
}
return arr.join("");
}
Here's the code I wrote. (needs to be refined for DRY principle)
function STC(string) {
const arr = [...string];
let output = '';
for (const letter of arr) {
if (letter == '_') {
output += arr[arr.indexOf(letter)+1].toUpperCase()
arr.splice(arr.indexOf(letter), 1)
} else {
output += letter;
}
}; return output;
}
I just add to the string instead of an array. I also delete the underscore. Tell me if it works.
function snakeToCamel(string) {
const arr = [...string];
arr.forEach((v, i) => {
if (v === "_") {
arr.splice(i+1,1, arr[i+1].toUpperCase());
arr.splice(i,1)
}
});
return arr.join("");
}
const result = snakeToCamel('a_b_c');
console.log(result);

Where should I place the return statement to get the desired output? Read my code comments. Thanks

This code is supposed to take in a string and return and return the string without vowels.
As you can see from the ouput below, it is working because it returns the first Coding is driving me crzy without a in crazy, and the 2nd without e and so on...
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (const vowel of vowels) {
for (let i = 0; i < charactersArray.length; i++) {
if (vowel === charactersArray[i]) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
//OUTPUT ON ONE LINE
//Coding is driving me crzy Coding is driving m crazy Codng s drvng me crazy Cding is driving me crazy Coding is driving me crazy
As suggested in one of the comments. Break down the problem by creating an isVowel() function and iterate over all chars in the string only once to check if a given character is a vowel:
function isVowel(c) {
return ['a','e','i','o','u'].includes(c);
};
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
for (let i = 0; i < charactersArray.length; i++) {
if (isVowel(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
This code runs in O(n * k) time complexity, where n is the length of the string and k is the number of vowels in English language (which is 5. So overall complexity is O(5n) = O(5).
You can use the includes method to check if the word of charactersArray[i] is a vowel, with a single loop is enought
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (let i = 0; i < charactersArray.length; i++) {
if (vowels.includes(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
If you want to match only the vowels you can make this:
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (let i = 0; i < charactersArray.length; i++) {
if (!vowels.includes(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
Here are some docs you could refer to :
string.includes
Spread Syntax
Filter
LowerCase
//you could do it like
function removeVowelFromString(string) {
let vowels = "aeiou";
return [...string].filter(x => !vowels.includes(x.toLowerCase())).join("");
}
console.log(removeVowelFromString("Will remove vowels from this string"))
I hope i was able to help.

Solving a Permutations problem with Heap's Algorithm in Javascript

I'm working through some "Kata's" on CodeWars.com, and am stuck on the Permutations problem.
Here is the problem: n this kata you have to create all permutations
of an input string and remove duplicates, if present. This means, you
have to shuffle all letters from the input in all possible orders.
Examples:
permutations('a'); // ['a']
permutations('ab'); // ['ab', 'ba']
permutations('aabb'); // ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']
The order of the permutations doesn't matter.
Here is my solution:
function permutations(string) {
const swap = (string, x, y) => {
const stringArray = string.split('')
const swapVar = stringArray[x]
stringArray[x] = stringArray[y]
stringArray[y] = swapVar
return stringArray.join('')
}
const permutate = (k, arr) => {
if (k === 1) {
return arr
} else {
for (let i = 0; i < k - 1; i++) {
if (k % 2 === 0) {
arr.push(swap(string, i, k-1))
} else {
arr.push(swap(string, 0, k-1))
}
}
permutate(k - 1, arr)
}
}
return permutate(string.length, [string])
}
When you pass in a single letter, it works fine. Two letters and it returns undefined. I've console logged the if statement block with the return and it should be returning the correct answer, but the result is still undefined. Considering it's getting the correct answer in the if statement and isn't progressing into the else block, I'm at a loss for why this isn't working.
Thank you in advance!
I figured it out - I was missing the return statement before the recursive function call.
Here is a basic solution
String.prototype.replaceAt = function(index, replacement) {
return this.substr(0, index) + replacement + this.substr(index +
replacement.length);}
var words = [];
var string = "lyes";
for(var i = 0;i< string.length;i++){
for(var j = 0;j<string.length;j++){
var tempChar;
if(i!==j){
tempChar = string[j]
var str = string.replaceAt(j,string[i])
str = str.replaceAt(i,tempChar)
if(!words.includes(str)){
words.push(str)
console.log(str)
}
}
}
}
console.log(words.length +" words found")

Captalize letter in a string in order and create an array to store

// Create a function that takes a string and turns it into a Mexican Wave.
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++)
{
if(smallarr[j][j].toUpperCase()==smallarr[j][j])
{
var c=smallarr[j][j].toLowerCase()
smallarr[j][j]=c
}
else {
var c=smallarr[j][j].toUpperCase()
smallarr[j][j]=c}
}
}
return smallarr
}
document.write(wave("edabit"))
//console.log(smallarr)
The output I expect is wave("edabit") ➞ ["Edabit", "eDabit", "edAbit", "edaBit", "edabIt", "edabiT"] but now the output is the same as the input.
Any advice is appreciated.
You can split the input string into an array of characters and then map over it replacing the current character with it's uppercase version:
const wave = (str) => {
return str
.split('')
.map((char, index) =>
str.substr(0, index) + char.toUpperCase() + str.substr(index + 1))
}
console.log(wave('edabit'));
You can use Array.from() to create an array from the string. In the callback (mapFn) get the current letter, and the current index, use them with String.substring() to build a new string with the uppercased letter.
const fn = str => Array.from(str, (c, i) =>
str.substring(0, i) + c.toUpperCase() + str.substring(i + 1)
);
const result = fn('edabit');
console.log(result);
You can try double Array.map() where second callback argument represents an index:
let input = "edabit";
let result = input.split('').map(
(_, i) => input.split('').map(
(char, j) => i === j ? char.toUpperCase() : char).join()
);
console.log(result);
EDIT:
The problem with your approach is that strings are immutable so you need to build a new string using slice like below:
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++){
smallarr[j] = smallarr[j].slice(0,j) + smallarr[j][j].toUpperCase() + smallarr[j].slice(j+1);
}
return smallarr
}
document.write(wave("edabit"))
console.log(smallarr)
or just using one loop:
function wave(str){
var smallarr=[]
for (var i=0;i<str.length;i++){
smallarr.push(str.slice(0,i) + str[i].toUpperCase() + str.slice(i+1))
}
return smallarr
}
console.log(wave("edabit"))
The main issue with your code is that you try to update a character in a string, but that is not possible. In JavaScript strings are immutable. Trying to assign to a certain index will have no effect to the string.
Instead you must rebuild a string where that one character is different. You can use slice to take parts of the string to help you build it.
Here is your code adapted to that effect:
function wave(str) {
var smallarr = []; // define as local
for (var j = 0; j < str.length; j++) {
let c = str[j]; // Use a variable to avoid duplicate code
if (c.toUpperCase() === c) {
c = c.toLowerCase();
} else {
c = c.toUpperCase();
}
// You cannot modify a string; you need to regenerate one
smallarr.push(str.slice(0, j) + c + str.slice(j+1));
}
return smallarr
}
console.log(wave("edabit"))
String.prototype.replaceAt=function(index, char) {
var a = this.split("");
a[index] = char;
return a.join("");
}
const createEdibet = ( word ) => {
console.log('word ' + word.split(''));
let array = word.split('')
array.map((letter, i) => {
let a = word.replaceAt(i, letter.toUpperCase());
console.log(a);
return a;
});
console.log(array)
// console.log(words)
}
createEdibet('edabit');
You could split the string, map the array and take the splittes string for another mapping by checking the index and use an upper case letter for matching indices.
const
wave = (string) => string
.split('')
.map((_, i, splitted) => splitted.map((c, j) => i === j ? c.toUpperCase() : c).join(''));
};
console.log(wave('edabit'));
A classic approach
function wave(string) {
var result = [],
i, j, temp;
for (i = 0; i < string.length; i++) {
temp = '';
for (j = 0; j < string.length; j++) {
temp += i === j ? string[j].toUpperCase() : string[j];
}
result.push(temp);
}
return result;
}
console.log(wave('edabit'));
If the array length is small you can use split, map, join like this:
let text = `edabit`;
let results = text.split('').map((char,index,original)=>{
let temp = [...original];
temp[index]=temp[index].toUpperCase();
return temp.join('');
});
console.log(results);
But in big array it's not optimized.

Categories

Resources