I'm a beginner in JavaScript, a self-learner using free pdf books, google and Stackoverflow.
I am stuck in a self assigned task ...
Swapping words with numeric digits, taking values from one text-box, performing swapping and putting result in another text-box. For example when I type six svn zro the output must be 670
But when I type something in textBox1 the result in textbox2 is "Undefined"**
Please debug it only using simple JavaScript, not jQuery.
Here is my code...
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function myFunction()
{
var a = ["one","two","tri","for","fiv","six","svn","egt","nin","zro"];
var b = [1,2,3,4,5,6,7,8,9,0];
var str = document.getElementById("textBox1").value;
var x = document.getElementById("textBox2").value;
var len = str.length;
for (var k=0; k < 200; k++)
{
var n = str.search(new RegExp(a[k], "i"));
var str1 = str.substring(0, n) + b[k] + str.substring(n+3, len);
document.getElementById('textBox2').value = str1.toString();
};
}
</script>
</head>
<body>
<input type="text" onkeyup="myFunction();" id="textBox1" autofocus/>
<br><br><br><br><br><br>
<input type="text" id="textBox2" />
</body>
</html>
The reason you get undefined is still because of the for loop.
When k reaches 10, a[10] does not exist and so returns undefined. This gets used as the replacement value in your string.
If you restrict k to the length of array a, you will not get undefined values.
The other issue is that you are always starting from the original string, so previous replacements are ignored. You need to always use str and not have str1.
Finally it is simpler to just use the replace() function rather than working out substrings - I tried to reuse your substring code but couldn't get it working.
So your function can become:
function myFunction() {
// values to search for - these can be strings or a regex string
var a = ["zro", "one", "two", "tri", "for", "fiv", "six", "svn", "egt", "nin"];
// get the input value
// we will perform all replacements against this
var str = document.getElementById("textBox1").value;
// loop through the array and replace each value in "str" with its index
// note we are reusing "str" each time to keep the previous replacements intact
// replace() can take either a string or a regex
for (var k = 0; k < a.length; k++) {
// put "zro" at the start of "a" so "k" is now the same as b[k] - no need for "b"
// create a RegExp from the string, set it to global replace (g) so it works if there is more than one match in the string, and case insensitive (i) in case they type "One"
str = str.replace(new RegExp(a[k], "gi"), k);
};
// store final value in the other textbox
document.getElementById('textBox2').value = str;
}
<input type="text" onkeyup="myFunction();" id="textBox1" autofocus="autofocus" />
<br/>
<input type="text" id="textBox2" />
EDIT/footnote: replace() is still simpler but you can use substring() - the problem with your original code is that if the regex does not match anything, n will be -1 and mess up str. So you need to check if n > -1 before you do the substring part:
for (var k = 0; k < a.length; k++) {
var n = str.search(new RegExp(a[k], "i"));
if(n > -1) {
// n+a[k].length is better than n+3, in case a[k] isn't 3 chars!
str = str.substring(0, n) + k + str.substring(n+a[k].length, str.length);
}
};
Here is my suggestion
function myFunction() {
var a = ["zro","one","two","tri","for","fiv","six","svn","egt","nin"]; // 0-based
var str = document.getElementById("textBox1").value;
var words = str.split(" "),len=words.length, str1=""; // split on words
for (var i=0; i < len; i++) { // run over length of array
var idx = a.indexOf(words[i]); // find the word in the index array
if (idx !=-1) str1+=idx;
}
if (str1) document.getElementById('textBox2').value=str1;
}
<input type="text" onkeyup="myFunction();" id="textBox1" autofocus/>
<br><br><br><br><br><br>
<input type="text" id="textBox2" />
If you want to have any entry containing any of the a[] strings, then this will do it
function myFunction1() {
var str = document.getElementById("textBox1").value;
var a = ["zro","one","two","tri","for","fiv","six","svn","egt","nin"];
var len = a.length;
for (var i=0; i < len; i++) {
var idx = str.indexOf(a[i]); // or str.toUpperCase().indexOf(a[i].toUpperCase())
if (idx !=-1) str = str.split(a[i]).join(i); // or use substr if case insensitive
}
if (str) document.getElementById('textBox2').value=str;
}
Related
I've got string with IDs and Names separated by ^ (between ID and Names) and ; (between sets) for example
var string = "1^John Smith;2^Sophia Williams;3^Emily Johnson;";
I need to get something like this
$('#1').html('<option value="1">John Smith</option><option value="2">Sophia Williams</option><option value="3">Emily Johnson</option>');
I tried loops but got stuck:
var string = "1^John Smith;2^Sophia Williams;3^Emily Johnson;";
var a = string.split(";"),
i;
for (i = 0; i < a.length; i++){
if (a[i] !== ""){
var b = a[i].split("^"),
i2;
for (var i2 = 0; i2 < b.length; i++) {
var name = b[i2];
console.log(name);
}
}
}
Im not sure that it's good way
Using Option()
new Option(text, value, defaultSelected, selected)
var string = "1^John Smith;2^Sophia Williams;3^Emily Johnson;"
var options = string.split(';').map(i => {
return new Option(...i.split('^').reverse())
})
$('#1').html(options)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="1"></select>
You can build a HTML string inside your loop by grabbing the first element from b as the value for your option and the second element from b to be the text in your option tag. You can then add a string HTML version of the option tag using these text and value components to the accumulated string each iteration of your for-loop:
var string = "1^John Smith;2^Sophia Williams;3^Emily Johnson;";
var a = string.split(";");
var html_str = "";
for (var i = 0; i < a.length-1; i++) { // loop to a.length-1 so you don't need an if-statement to check blanks
var b = a[i].split("^");
var val = b[0];
var txt = b[1];
html_str += '<option value="' + val +'">' + txt +'</option>';
}
$('#one').html(html_str);
console.log(html_str);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="one"></select>
An alternative approach could be to use a regular expression to get the components from your string an convert it to your desired HTML string by using .replace() with a replacement function:
var string = "1^John Smith;2^Sophia Williams;3^Emily Johnson;";
var html_str = string.replace(/(\d+)\^([^;]+);/g, (_, val, txt) => `<option value="${val}">${txt}</option>`);
$('#one').html(html_str);
console.log(html_str);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="one">
</select>
The above regular expression:
(\d+)\^: Groups any digits (group 1) which have a carat ^ following them
([^;]+);: Groups any characters which are not a semi-colon ; (group 2), which are followed by a semi-colon.
These groups are formed for each occurrence in your string, and then used in the .replace() method's callback, where group 1 is val and group 2 is txt.
I have written a function called reverseStr that takes in a string as a parameter and returns the string but with the characters in reverse.
For example: reverseStr('bootcamp'); => 'pmactoob'
Following is my program:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0; i <= splitStr.length -1 ; i++)
{
for(var j = splitStr.length - 1; j >= 0; j--)
{
reverseString[i] = splitStr[j]
}
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
If I run the function reverseStr("bootcamp") it returns bbbbbbbb.
Does anyone see a problem with the code?
Note: I DONOT WANT TO USE REVERSE() BUILT-IN FUNCTION
However, I found success with the following code but still need an answer to my initial question
function reverseStr(str)
{
var splitStr = str.split("");
reverseStr = "";
for(var i = splitStr.length - 1; i >= 0 ; i = i - 1)
{
reverseStr += splitStr[i];
}
return reverseStr;
}
You don't need to double-iterate through the characters, i.e., do not need to nest for loops. Iterate once and grab the chars in reverse order, like this:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0, j=splitStr.length-1; i <= splitStr.length -1 ; i++, j--)
{
reverseString[i] = splitStr[j]
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
You can see that here the loop goes on for as long as i <= splitStr.length -1,ie, length of the string. This is sufficient to get the mirroring character (i versus Array.length-i).
Here is a working snippet to demo:
var reverseStr = function(str) {
let result = String();
for(let i = str.length-1; i >= 0; i--) {
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
Perhaps a more elegant way to achieve the same (apart from Array.prototype.reverse()) would be to use String.prototype.chatAt(). This would avoid two conversions to and from an array, and also save you one variable. Granted, the code is much shorter and more obvious in what it is doing.
var reverseStr = function(str) {
let result = String(); // An empty string to store the result
for(let i = str.length-1; i >= 0; i--) { // Iterate backwards thru the chars and add to the result string
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''); // Original return method of the author
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
The problem is that your nested for loop runs its whole course before it returns to the outer for loop. So, it just repeats one character the amount of times equal to the length. Instead of having another for loop, just add a simple counter for j like j++ inside your outer for loop and use that value with the i value.
To the original poster, consider this:
If you know the length of the original string, you therefore know the offset of that last position within the original string.
Iterate through the original string in reverse order, appending the current position's value to a new string. The new string would be the reverse of the original.
Aydin's example is essentially correct. Here's my very similar version, with comments:
function reverseString(inputString) {
// create a new empty string
var newString = "";
// iterate through the characters of the string in reverse order,
// appending to the new string
for (var i = inputString.length - 1; i >= 0; i--) {
newString += inputString[i];
}
return newString;
}
console.log(reverseString('bootcamp'));
I have an array of names from A-Z in ABC order and I want to get all the names from A to J. Is there any way to do this besides checking the first letter of each character against an array of all the letters from A to J?
Example:
var array=['Amy','Dolly','Jason','Madison','Patricia'];
And I want an array of Amy, Dolly and Jason.
You can use filter function like
var array=['Amy','Dolly','Jason','Madison','Patricia'];
var filtered = array.filter(function(el){return el[0]>='A' && el[0]<='J'})
var array=['Amy','Dolly','Jason','Madison','Patricia'];
var filtered = array.filter(function(el){return el[0]>='A' && el[0]<='J'});
document.getElementById('res').innerHTML = JSON.stringify(array) + '<br />' + JSON.stringify(filtered);
<div id="res"></div>
Code above checking all element in array, if you want avoid it and array already sorted, you can use simple for loop
var array=['Amy','Dolly','Jason','Madison','Patricia'];
var result=[];
for(var i=0;i<len=array.length; i<len && (array[i][0]>='A' && array[i][0]<='J'); i++){
result.push(array[i]);
}
or same in one liner
for(var i=0, result=[], len=array.length; i<len && (array[i][0]>='A' && array[i][0]<='J');result.push(array[i]),i++);
in result - filtered collection;
Yet another way find index and then use slice like
for(var i=0, len=array.length; i<len && (array[i][0]>='A' && array[i][0]<='J');i++);
var result = array.slice(0,i);
Interesing way from #dandavis in comment with filter and regex
var filtered = array.filter(/./.test, /^[A-J]/);
it altervative for
var regex = /^[A-J]/;
var filtered = array.filter(function(el){ return regex.test(el); });
You can do this using regular expression..
var array=['Amy','Dolly','Jason','Madison','Patricia'];
var reg = new RegExp('^[A-J]');
var arrTemp=[];
var intLength = array.length;
for(var i=0;i<intLength ;i++){
if(reg.test(array[i])) {
arrTemp.push(array[i])
}
}
console.log(arrTemp)
If you want consider case-sesitive nature then you can write your regular expression like
var reg = new RegExp('^[A-Ja-j]');
You can use the ascii-value of the character and use a filter to get the result you want. The character code value of "J" is 74 and for "A" it is 65.
array.filter(function(v) { return v.charCodeAt(0) >= 65 && v.charCodeAt(0) <= 74 })
var array = ['Amy', 'Dolly', 'Jason', 'Madison', 'Patricia'],
bound = { lower: 'A', upper: 'J' },
newArray = [],
i = 0, j, l = array.length;
// lookup for the first element of the array which is smaller than the lower bound
while (i < l && array[i][0] < bound.lower) {
i++;
}
j = i;
// lookup for the end of the upper bound and skip the rest
while (j < l && array[j][0] <= bound.upper) {
j++;
}
// build new array
newArray = array.slice(i, j);
func = function() {
val = document.getElementById('word').value;
first = val.charAt(0).toUpperCase();
rest = val.substring(1).toLowerCase();
valConvert = first + rest;
undersc = '_';
fullUndersc = '';
for (var i = 2; i < val.length; i++) {
fullUndersc = fullUndersc + undersc;
}
wordToGuess = valConvert.charAt(0) + fullUndersc + valConvert.slice(-1);
document.getElementById('form').innerHTML = wordToGuess;
document.getElementById('letterIn').style.display = 'block';
guess = function() {
var charac = document.getElementById('letter').value;
for (var i = 1; i < val.length -1; i++) {
if (charac == valConvert.charAt(i)) {
wordToGuess = wordToGuess.replace(new RegExp(wordToGuess.charAt(i), 'i'), charac);
document.getElementById('form').innerHTML = wordToGuess;
}
}
}
}
The outer function takes user's input, converts letters to a proper case (upper case and lower case), leaves first and last letter as it is and swaps the rest of characters with _.
The inner function (guess) again takes user's input (just one character) and checks whether or not the character exists in user's previous input. This function works but I want it to replace _ with the input letter IN THE PROPER POSITION.In short - I am trying to make The Hangman game.Any help will be much appreciated.
<!--HTML
<form onSubmit="func(); return false" id="form">
Type in a word below<br /><input class="" id="word" type="text" autofocus />
</form>
<form onSubmit="guess(); return false" id="letterIn">
Enter a letter: <input class="" id="letter" type="text" size="1" maxlength="1" autofocus />
</form>
-->
You'll need to keep track of the original phrase as well as the clues.
var phrase = 'A phrase to guess',
clue = '_ _____ __ _____';
function updateClue (guess) {
// split the clue into an array
clue = clue.split('');
// loop through the characters in the phrase
for (var i = 0; i < phrase.length; i++) {
// if the letter in the phrase matches the guess
if (phrase.charAt(i).toLowerCase() === guess.toLowerCase()) {
// replace the corresponding character in the clue
clue[i] = phrase.charAt(i);
}
}
// convert the clue array back into a string
clue = clue.join('');
return clue;
}
Here's silly (working) example.
How to write a script in javascript which check all lines ("Line1\nLine2\nLine3...") in a string and if there are duplicate lines then just leave one and ignore br tags?
var s = "Hello world\n<BR>\nThis is some text\nThis is some text\n<BR>\nThis is some text"
line1 = "Hello world"
line2 = "<BR>"
line3 = "This is some text"
line4 = "This is some text"
line5 = "<BR>"
line6 = "This is some text"
var result = "Hello world\n<BR>\nThis is some text\n<BR>"
line 1 = "Hello world"
line 2 = "<BR>"
line 3 = "This is some text"
line 4 = "<BR>"
I think the shortest solution is this.
myStr
.split("\n")
.filter((item, i, allItems) => {
return i === allItems.indexOf(item);
})
.join("\n");
var pieces = s.split("\n"); //This will split your string
var output = []; //Output array
for (var i = 0; i < pieces.length; i++) { //Iterate over input...
if (pieces[i] == '<BR>' || output.indexOf(pieces[i]) < 0) { //If it is <BR> or not in output, add to output
output.push(pieces[i]);
}
}
var newS = output.join("\n"); //Concatenates the string back, you don't have to do this if you want your lines in the array
Here we have the jsFiddle: http://jsfiddle.net/7s88t/
For you knowledge, the indexOf function returns the position where pieces[i] is at output array. If it is not found, it returns -1. That is why I check if it is less than zero.
Hope I have helped.
EDIT
As you requested, to take lower case:
if (pieces[i].toLowerCase() == '<br>' || pieces[i].toLowerCase() == '<br/>' || pieces[i].toLowerCase() == '<br />' || output.indexOf(pieces[i]) < 0) {
1) divide your text into an array by line break:
var arr = s.split("\n");
2) Remove all duplicate entries:
var str;
for(var i=0; i<arr.length; i++) {
str = arr[i];
//Takes into account all bad forms of BR tags. Note that in your code you are using
//invalid br tags- they need to be <br /> (self-closing)
if(inArray(str, arr) && str != "<br>" && str != "<br/>" && str != "<br />"){
arr.splice(i, 1);
}
};
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
3) Make them back into a string
//Note joining with newline characters will preserve your line outputs :)
var output = arr.join("\n");
This approach is good because it avoids using regex, doesn't even need to consider <br /> tags, and uses native JS meaning you can put it anywhere you want. I didn't test this code, I just wrote it out so it may contain errors. But it should be a good starting point.
Cheers!