How do I finish this loop? Concatenate two previous characters - javascript

I'm making a function that when you give it a string, it will return the uppercase of the even numbered chars and the lower case of the odd numbered ones. So if you give it "HELLO" it will give you "HeLlO". This is obviously wrong since it only works for the first two characters. How do I complete the loop so that it doesn't keep concatenating the strings together?
function evenOddChange(source)
{
var i;
var result;
i = 0;
result = "";
while ( i < (source.length))
{
result = result + source.toUpperCase().charAt(i) + source.toLowerCase().charAt(i + 1);
i = i + 1;
}
return result;
}

You can usemodulo to check if its even or Odd.
function evenOddChange(source)
{
var i;
var result;
i = 0;
result = "";
while ( i < (source.length))
{
if(i%2==0){
result = result + source.toUpperCase().charAt(i);
}else{
result = result + source.toLowerCase().charAt(i);
}
i = i + 1;
}
return result;
}

Just use modulus to find if the index is odd or even and then use bracket notation.
function evenOddChange(source) {
var i = 0, result = "";
while (i < source.length)
result += source[i][i++ % 2 == 0 ? "toUpperCase" : "toLowerCase"]();
return result;
}
Note that when we are doing i++ % 2, the modulus operator operates on the value of i before we increment it. The increment effect will be felt only in the next iteration.

Increment by 2, not 1:
i = i + 2;
Not you are changing i and i+1, incrementing by only one will overwrite the i+1 change. This simple change will fix your problem.

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)

Replacing alternative letters in a string to either "!" or "?"

This
I'm able to return T!d!y. But i need T!d?y. I'm new to JS and I cant figure it out =(
function change(str) {
newString = str.split("");
for (let i = 1; i < newString.length - 1; i+=2) {
newString[i] = "!";
//newString[i] = "?";
}
return(newString.join("")); }
console.log(change("Teddy")); should return T!d?y
Use modulo to check whether the i being iterated over is one of the 3-7-11 sequence or the 1-5-9 sequence - then you can determine which character to insert.
function change(str) {
const arr = str.split("");
for (let i = 1; i < arr.length - 1; i += 2) {
arr[i] = i - 1 % 4 === 0
? "!"
: "?";
}
return arr.join("");
}
console.log(change("Teddy"));
Also remember
Declare your variables - doing newString = without a const (or something) before it implicitly creates a global variable, which is very often not what you want
.split returns an array; newString is not an accurate description of what the variable contains (perhaps instead call it arr or newArray or characters, or something like that)
You can add a check and update variable to be replaced.
Few pointers:
When looping, you will have to loop till last character. i < arr.length - 1 will cause issues for certain scenarios.
function change(str) {
const possibilities = [ "!", "?", "*" ];
let index = 0;
let newString = str.split("");
for (let i = 1; i < newString.length ; i += 2) {
newString[i] = possibilities[index % possibilities.length];
index++
}
return (newString.join(""));
}
console.log(change("Teddy"));
console.log(change("Javascript"));

Undefined in Split String

i have a function to split string into 2 part, front and back. Then reverse it to back and front. Here is my code
function reverseString(string) {
let splitString = ""
let firstString = ""
for(i = 0; i <= string.length/2 - 1; i++) {
firstString += string[i]
}
for(i = string.length/2; i <= string.length; i++) {
splitString += string[i]
}
return splitString + firstString
}
Sorry for bad explanation, this is test case and expected result (first one is expected result, the second one is my result)
console.log(reverseString("aaabccc")); // "cccbaaa" "undefinedundefinedundefinedundefinedaaa"
console.log(reverseString("aab")); // "baa" "undefinedundefineda"
console.log(reverseString("aaaacccc")); // "ccccaaaa" "ccccundefinedaaa"
console.log(reverseString("abcdefghabcdef")); // "habcdefabcdefg" "habcdefundefinedabcdefg"
could you help me, whats wrong with it. Thank you
You could try another approach and use the slice function
function reverseString(string)
{
if (string.length < 2) { return string; }
let stringHalfLength = string.length / 2;
let isLengthOdd = stringHalfLength % 1 !== 0;
if (isLengthOdd) {
return string.slice(Math.ceil(stringHalfLength), string.length + 1) + string[Math.floor(stringHalfLength)] + string.slice(0, Math.floor(stringHalfLength));
}
return string.slice(stringHalfLength, string.length + 1) + string.slice(0, stringHalfLength);
}
console.log(reverseString("aaabccc") === "cccbaaa");
console.log(reverseString("aab") === "baa");
console.log(reverseString("aaaacccc") === "ccccaaaa");
console.log(reverseString("abcdefghabcdef") === "habcdefabcdefg");
A more efficient way to reverse the string would be to split the string, then use the built-in reverse javascript function (which reverses the elements of the split string), and then re-join the elements using the join function.. No need to re-invent the wheel?
You can concatenate the functions in shorthand (.split.reverse.join etc...) so your function would look something like this:
function reverseString(string) {
return string.split("").reverse().join("");
}
Try it out!
function reverseString(string) {
return string.split("").reverse().join("");
}
console.log(reverseString("hello"));
console.log(reverseString("aaabbbccc"));
If there's a particular reason you're opting not to use the in-built functions (i.e. if I've missed something?) , feel free to comment.
The short version of what you need:
function reverseString(string) {
const splitPosition = Math.ceil(string.length / 2);
return string.substring(splitPosition) + string.substring(0, splitPosition);
}
The key to your question is the middle element. To accomplish that, you probably want to use Math.floor that round under.
console.log(reverseString("aaabccc")); // "cccbaaa"
console.log(reverseString("abcdefghabcdef")); // "habcdefabcdefg"
function reverseString (str) {
if (str.length<2) {
return str
}
var half = Math.floor(str.length / 2);
return (str.slice(-half) + (str.length%2?str[half]:"") + str.slice(0,half));
}
reverseString('')
> ""
reverseString('1')
> "1"
reverseString('12')
> "21"
reverseString('123')
> "321"
reverseString('1234')
> "3412"
reverseString('12345')
> "45312"
reverseString("aaabccc")
> "cccbaaa"
reverseString("abcdefghabcdef")
> "habcdefabcdefg"
So basically your problem is not to grab 2 parts of the string and rearrange, it is to grab 3 parts.
1 part: str.slice(0,half)
2 part: str.length%2 ? str[half] : ""
3 part: str.slice(-half)
The second part is empty if the string length is even and the middle character if is odd.
So the code version in long self explanatory code:
function reverseString (str) {
if (str.length<2) {
return str
}
var half = Math.floor(str.length / 2);
var firstPart = str.slice(0,half);
var midlePart = str.length % 2 ? str[half] : ""; // we could expand also this
var endPart = str.slice(-half);
return endPart + midlePart + firstPart;
}
And also, notice the precondition, so I don't have to deal with the easy cases.
Also, in your code, you got undefined because you access in the last loop to:
string[string.length] you need to change <= by <

How do I run a function over and over by using parameters?

My case:
function randomLetter(){
var random = letter[Math.floor(Math.random()*26)];
return random;
}
function randomWord(wordLength){
var random = randomLetter() + randomLetter() + randomLetter();
return random;
}
How do I write a code that run the randomLetter() function x times using parametes.
Example: I write 3 in the parameter, and the function will give me three random letters.
So instead of writing randomLetter() + randomLetter() + randomLetter(), I will just write randomWord(3), and I will get three random letters.
Another approach, which buffers each letter into an array and returns the joined array.
function randomWord(wordLength){
var letters = [];
for (var i = 0; i < wordLength; i++) {
letters.push(randomLetter());
}
return letters.join("");
}
Or recursion:
var letters = "abcdefghijklmnopqrstuvwxyz"
function randomLetter() {
return letters.charAt(Math.floor((Math.random() * 100)) % letters.length)
}
function getLetters(count) {
if (count-- < 1) return "";
return getLetters(count) + randomLetter() + ","
}
document.getElementById("output").innerText = getLetters(4)
<div id="output" />
For this you could use a for loop like:
function randomWord(wordLength){
var random =''
for (var i = 0, i<wordLength, i++) {
random += randomLetter();
}
return random;
}
the first parameter in the parentheses after the 'for' keyword initializes the i variable with 0. The next value i<wordLength is the stop condition, which will test at the beginning of each run if the condition is still true, otherwise it will stop looping. The third i++ is what runs every time a loop finishes, in this case it increments i by one, which is identical to i = i + 1.
here is some more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration
You can use a for-loop:
function randomWord(x){
var random = [];
for(var a = 0; a < x; a++){
random[a] = randomLetter();
}
return random.join("");
}
Yet another recursive solution:
function randomLetter() {
return ('qwertyuiopasdfghjklzxcvbnm')[Math.floor(Math.random()*26)];
}
function randomWord(wordLength) {
return (wordLength > 0) ? (randomWord(wordLength - 1) + randomLetter()) : '';
}
console.log( randomWord(10) );

Javascript: Get Length of a String without Length Propery, And with Slice

I know, it's a weird one! But why does this not work?
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = subString.slice(counter);
}
return counter;
}
var output = getStringLength('hello');
console.log(output); // --> expecting 5, but getting 3 (??)
I really want to do it with slice! The original challenge was to not use the length property, and I figured this out, which works fine:
function getStringLength(string) {
var long = 0;
while (string[long] !== undefined) {
long++;
}
return long;
}
you were mutating your string, this should work for you
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = subString.slice(1);
}
return counter;
}
var output = getStringLength('hello');
console.log(output); // 5
The main difference was that I was doing
subString = subString.slice(1);
instead of
subString = subString.slice(counter);
which always decreased length by 1
The problem is the code substring.slice(counter) First time, you chop off 1 character. Then you chop off 2 characters from the already-chopped substring. Either chop off 1 at a time, or chop off the increasing amount from the original string. So that's either substring.slice(1) or string.slice(counter)
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = substring.slice(1);
}
return counter;
}
var output = getStringLength('hello');
console.log(output);
To achieve expected result, use below option
function getStringLength(arr){
return arr.lastIndexOf(arr.slice(-1))+1
}
var output = getStringLength('hello');
console.log(output);
https://codepen.io/nagasai/pen/gGPWEE?editors=1111
Option2: As type of array is object,below option works too
function getStringLength(arr){
return Object.keys(arr).pop()*1 + 1
}
var output = getStringLength('hello');
console.log(output);
https://codepen.io/nagasai/pen/PJZmgg?editors=1111
Check the below updated options to handle empty and numbers
https://codepen.io/nagasai/pen/GMoQgy?editors=1111
https://codepen.io/nagasai/pen/YrweWr?editors=1111
Perhaps a slightly shorter answer:
function getStringLength(string) {
var counter = 0;
while (string.slice(counter)) {
counter++;
}
return counter;
}
var outputHello = getStringLength('hello');
console.log(outputHello); // 5
var outputEmpty = getStringLength('');
console.log(outputEmpty); // 0

Categories

Resources