Iterate through arrays inside a .replace() - javascript

I need to replace all letters from a string to other signs (stored in an array).
for (var i = 0; i < letters.length; i++) {
output.value = input.value.replace(letters[i], signs[i]); //this should be global
}
var input = document.getElementById('input');
var output = document.getElementById('output');
var letters = ['a', 'b', 'c'];
var signs = ['.', ':', '-'];
function run() {
for (var i = 0; i < letters.length; i++) {
output.value = input.value.replace(letters[i], signs[i]); //this should be global
}
}
<input type="text" id="input" onkeyup="run();">
<input type="text" id="output">
If the input says "abc" the output should say ".:-"

The problem is the new updated value after the replacing step, what you need to do is store the new value and after replacing the whole set of chars, then set the new value to output.value.
An important detail here is that you need to replace all chars which match with a specific letter, to accomplish that you can build a Regexp and use the flag global g.
new RegExp(letters[i], 'g');
^
|
+---- This is the flag!
Another thing I recommend is to embrace the function addEventListener to bind an event to elements.
var input = document.getElementById('input');
var output = document.getElementById('output');
var letters = ['a', 'b', 'c'];
var signs = ['.', ':', '-'];
function run() {
var currentInput = this.value;
for (var i = 0; i < letters.length; i++) {
var rg = new RegExp(letters[i], 'g');
currentInput = currentInput.replace(rg, signs[i]);
}
output.value = currentInput;
}
input.addEventListener('input', run);
<input type="text" id="input">
<input type="text" id="output">

I would turn you letters and signs into a lookup table like:
{a: ',', b:':' // etc..}
so you don't need to search through the letters with each keyup. You can do this once at the beginning, or just use the format to begin with. The you can just map() it to a new value
var input = document.getElementById('input');
var output = document.getElementById('output');
var letters = ['a', 'b', 'c'];
var signs = ['.', ':', '-'];
let signMap = letters.reduce((a, c, i) => {
a[c] = signs[i]
return a
}, {})
function run() {
output.value = [...input.value].map((i) => signMap[i]).join('')
}
<input type="text" id="input" onkeyup="run();">
<input type="text" id="output">
Another alternative if your letters are always going to be in order is to use the character codes for the lookup in signs. You can also use replace with a generic regex and pass the letter to the function. Then you can avoid the loop altogether. This will ignore input not in the signs, but you could easily just include the original letter if it's not in the signs array.
var input = document.getElementById('input');
var output = document.getElementById('output');
var signs = ['.', ':', '-'];
let offset = 'a'.charCodeAt(0)
function run() {
output.value = input.value.replace(/./g, s => signs[s.charCodeAt(0) - offset] || '' )
}
<input type="text" id="input" onkeyup="run();">
<input type="text" id="output">

My opinion:
I prefer to create one Object to store all mappings, like what signMap does.
create one regex like (a|b|c|ef) (so you don't need to loop each character for input string, then even it can support multiple letters). PS: assuming the elements in Array=letters are not special letters, if yes, you need to adjust Regex Expression for your real case.
then uses String.replace(regex, (replacement)=>{return 'what you need'})
like below simple demo:
var input = document.getElementById('input');
var output = document.getElementById('output');
var letters = ['a','b','c', 'ef'];
var signs = ['.',':','-', '#'];
let regex = new RegExp('('+letters.join('|') + ')', 'g') //assume the elements in Array=letters doesn't have special characters.
let signMap = letters.reduce((pre, cur, curIndex) => {
pre[cur] = signs[curIndex]
return pre
}, {})
function run() {
output.value = input.value.replace(regex, (item)=> {
return signMap[item]
});
}
<input type="text" id="input" onkeyup="run();">
<input type="text" id="output">

Related

how to enter text and then convert It to other values via java script

I made a script that converts letters into numbers using "var". What is the best way to make a html page to input the text and then translate it to numbers using the script bellow.
var a='1*'
var b="2*"
var c="3*"
var d="4*"
var e="5*"
var f="6*"
var g="7*"
var h="8*"
var i="9*"
var j="10*"
...
var output= [a+b].join('');
You need a function that translate the letters to numbers then you can call it from an input. The result of translation can be displayed in a span for example.
function translateLetterToNumber(event) {
const value = event.target.value;
let translatedText = value.charCodeAt(0) - 96;
if (value.length > 1) {
const splittedValue = value.split('');
const translatedLetters = splittedValue.map(letter => letter.charCodeAt(0) - 96);
translatedText = translatedLetters.join('');
}
document.getElementById('result').textContent = translatedText;
}
<input type="text" onkeyup="translateLetterToNumber(event)" />
<span id="result"></span>
You can get the letter you like and use charCodeAt(letter) to get the Unicode number for that letter. In Unicode for a is 97. So if a = 1, b = 2 you have to subtract it by 96:
var letter = document.querySelector('input');
letter.addEventListener('change', function() {
let number = letter.value.charCodeAt(0) - 96;
console.log(`${letter.value} => ${number}`);
})
<input type="text" maxLenght="1"><label>type a single letter</label>

Match all phrases and push element to array

I am trying to match all typed phrases(characters) with main array. I have a big array, when user types something i want to search my array and show only matching entries, for example: if user types puzzle then from my array 'my puzzle starts','enter your puzzle' these both should match.
I have created Fiddle here, here is my html code
Search: <input autocomplete="off" type="text" id="search" /><br />
Results: <input type="text" id="results_count" /><br />
<textarea id="results_text" style="width:300px; height:500px"></textarea>
My js code
var string =['1234sud','man in puzzle','rocking roll','1232 -powernap','all_broswers'];
$('#search').keyup(function() {
var search = $(this).val();
var resultsText = $('#results_text');
var resultsCount = $('#results_count');
if (!search) {
resultsText.val('');
resultsCount.val('0');
return;
}
var j = 0, results = [],result;
for (var i=0;i<string.length;i++){
var rx = new RegExp('"([*'+search+'*])"','gi');
if (rx.exec(string[i])) {
results.push(string[i]);
j += 1;
if (j >=100)
break;
}
}
//results=string;
resultsText.val(results);
console.log(results)
resultsCount.val(j);
});
I am not able to write that regular expression which matches types phrases (characters) with array and pushes matching element to result array. Any help will be appreciated thanks in advance.
var string = ['1234sud', 'man in puzzle', 'rocking roll', '1232 -powernap', 'all_broswers'];
$('#search').keyup(function() {
var search = $(this).val();
var resultsText = $('#results_text');
var resultsCount = $('#results_count');
if (!search) {
resultsText.val('');
resultsCount.val('0');
return;
}
var j = 0,
results = [],
result;
for (var i = 0; i < string.length; i++) {
if (string[i].indexOf(search) > -1) {
results.push(string[i]);
j += 1;
if (j >= 100)
break;
}
}
//results=string;
resultsText.val(results);
console.log(results)
resultsCount.val(j);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
Search: <input autocomplete="off" type="text" id="search" /><br /> Results: <input type="text" id="results_count" /><br />
<textarea id="results_text" style="width:300px; height:500px"></textarea>
Use String.prototype.indexOf() function, it's exactly what you want to accomplish.
Normalize the case and use Array#filter()
$('#search').keyup(function() {
var search = $(this).val().toLowerCase(),
// add validation that search isn't empty, return if it is
// create results array
results = string.filter(function(s){
return s.toLowerCase().indexOf(search)>-1;
})
// do something with results
})
Your simplest solution: don't use regex.
For this particular problem, you're best off just looking for the index of the substring, using indexOf.
const words = ['hello', 'jello', 'cake', 'pie'];
const term = 'ello';
const result = words.filter(word => word.indexOf(term) > -1);
console.log(result);
You don't specify, but if you want word only matches (as oppose to partial word matches like I have above), you could pad it with a space.
If you insist on using regex, then all you need is the word itself:
const words = ['hello', 'jello', 'cake', 'pie'];
const term = 'ello';
const result = words.filter(word => (new RegExp(term, 'gi')).test(word));
console.log(result);
You don't need any fancy symbols or groupings or anything.
A regex of /ello/ just means "find this word anywhere in the string". Since there isn't a ^ or $, it isn't limited by start or end, so no need for wildcards.
Also, use test() instead of exec(), since test() resolves to a boolean, it's more accurate for an if statement.
Again, if you want whole words, you could just wrap it in spaces with the start and end having /[^\s]word[\s$]/ which would means "either a space or the start of the phrase" and "either a space or the end of the phrase".
Maybe you want to use a filter() for that task.
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
// const result = words.filter(word => word.indexOf(words.search) >= 0);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Hope this helps.
Use String.match if you need exact match:
if (search.match(string[i])) {
results.push(string[i]);
j += 1;
}
Or dynamically created regex for case of not exact match:
var rxs = '.*' + search + '.*';
var rx = new RegExp(rxs,'gi');
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
let checkWord = "elite"
words.forEach(x=>{
checkWord.match(new RegExp(x)
})

Separate characters and numbers from a string

I have a string variable that contain character and numbers like this
var sampleString = "aaa1211"
Note that variable always start with a character/s and end with number/s. Character and number size is not fixed. It could be something like followings
var sampleString = "aaaaa12111"
var sampleString = "aaa12111"
I need to separate the characters and numbers and assign them into separate variables.
How could I do that ?
I try to use split and substring but for this scenario I couldn't apply those. I know this is a basic question but i'm search over the internet and I was unable to find an answer.
Thank you
Please use
[A-Za-z] - all letters (uppercase and lowercase)
[0-9] - all numbers
function myFunction() {
var str = "aaaaAZE12121212";
var patt1 = /[0-9]/g;
var patt2 = /[a-zA-Z]/g;
var letters = str.match(patt2);
var digits = str.match(patt1);
document.getElementById("alphabets").innerHTML = letters;
document.getElementById("numbers").innerHTML = digits;
}
Codepen-http://codepen.io/nagasai/pen/pbbGOB
A shorter solution if the string always starts with letters and ends with numbers as you say:
var str = 'aaaaa12111';
var chars = str.slice(0, str.search(/\d/));
var numbs = str.replace(chars, '');
console.log(chars, numbs);
You can use it in a single regex,
var st = 'red123';
var regex = new RegExp('([0-9]+)|([a-zA-Z]+)','g');
var splittedArray = st.match(regex);
var num= splittedArray[0];
var text = splittedArray[1];
this will give you both the text and number.
Using Match
const str = "ASDF1234";
const [word, digits] = str.match(/\D+|\d+/g);
console.log(word); // "ASDF"
console.log(digits); // "1234"
The above will work even if your string starts with digits.
Using Split
with Positive lookbehind (?<=) and Positive lookahead (?=):
const str = "ASDF1234";
const [word, digits] = str.split(/(?<=\D)(?=\d)/);
console.log(word); // "ASDF"
console.log(digits); // "1234"
where \D stands for not a digit and \d for digit.
Use isNaN() to differentiate
var sampleString = "aaa1211"
var newnum =""
var newstr =""
for(var i=0;i<sampleString.length;i++){
if(isNaN(sampleString[i])){
newstr = newstr+sampleString[i]
}else{
newnum= newstr+sampleString[i]
}
}
console.log(newnum) //1121
console.log(newstr) //aaa
If you're like me, you were looking to separate alphabets and numbers, no matter what their position is, Try this:
var separateTextAndNum = (x) => {
var textArray = x.split('')
var text = []
var num = []
textArray.forEach(t=>{
if (t>-1) {
num.push(t)
} else {
text.push(t)
}
})
return [text, num]
}
For ex - if you try this:
separateTextAndNum('abcd1234ava') // result [["a","b","c","d","a","v","a"],["1","2","3","4"]]
This isn't beautiful but it works.
function splitLettersAndNumbers(string) {
var numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
var numbers, letters, splitIndex;
for (var i = 0; i < string.length; i++) {
if (numbers.indexOf(string[i]) > -1) {
letters = string.substring(0, i);
numbers = string.substring(i);
return [letters, numbers];
}
}
// in the chance that you don't find any numbers just return the initial string or array of the string of letters
return [string];
}
Essentially just looping through the string until you find a number and you split it at that index. Returning a tuple with your letters and numbers. So when you run it you can do something like this:
var results = splitLettersAndNumbers(string);
var letters = results[0];
var numbers = results[1];
A functional approach...
var sampleString = "aaaaa12111";
var seperate = sampleString.split('').reduce(function(start , item){
Number(item) ? start[0] += item : start[1] += item;
return start
},['',''])
console.log(seperate) //["12111", "aaaaa"]
You can loop through the string length, check it & add to the variable.
It is not clear if you want to assign each of the character to a variable or all alphabets to one variable & integers to another.
var sampleString = "aaa12111"
var _num = "";
var _alp = "";
for (var i = 0; i < sampleString.length; i++) {
if (isNaN(sampleString[i])) {
_num += sampleString[i];
} else {
_alp += sampleString[i];
}
}
console.log(_num, _alp)

Test a Textarea for All Keywords in an Array

I found a variation on this code elsewhere in StackOverflow. It takes all words from a textarea and converts them into a regular expression. It then tests an array to see if all the words in the regex are contained in the array:
<textarea id="inputtext" type="text"></textarea>
<input id="searchbutton" type="button" value="Click me" />
var links = new Array("taxi","Alpha","runway");
$("#searchbutton").click(function () {
var query = $("#inputtext").val();
var querywords = query.split(',');
for (var i = 0; i < querywords.length; i++) {
var regex = new RegExp('(?=.*\\b' + querywords[i].split(' ').join('\\b)(?=.*\\b') + '\\b)', 'i', 'g');
for (var j = 0; j < links.length; j++) {
if (regex.test(links[j])) {
console.log("Correct");
}
}
}
});
How can I reverse the process so the program returns "true" if the textarea words includes all of the keywords within the array? For example, if the textarea had the sentence "Taxi to the runway via taxiway alpha," and the array named "links" contained the keywords "taxi" "alpha" and "runway", the program would return "true".
That script you have seems to check if any of the words appears somewhere in the array. What you want is the every Array method:
var text = "Taxi to the runway via taxiway alpha",
links = ["taxi", "alpha", "runway"];
console.log( links.every(function(word) {
return new RegExp("\\b"+word+"\\b", "i").test(text);
}) ); // true
The methods provided by other answers are simple, but they could be more efficient.
It's almost always better to use an object as a map to speed up lookups instead of having to search the entiry array everytime.
var words = ['word1', 'word2'],
wordsMap = 'text area content, word1 and word2'.split(/\W+/).reduce(function (obj, word) {
obj[word] = true;
return obj;
}, {}),
areWordsAllContained = words.every(function (word) {
return wordsMap[word.toLowerCase()];
});
console.log(areWordsAllContained); //true
EDIT: I've changed the splitting regex from \s+ to \W+ to make sure that it splits on every non-word characters.
A non-regex way would be:
var arr = ['word1', 'word2'], haystack = textArea.value.toLowerCase().split(/\s+/);
var result = true, i = 0;
for(i=0; i<arr.length; i++) {
if(haystack.indexOf(arr[i].toLowerCase()) === -1) {
result = false;
break;
}
}

Looping Through an Array of Characters

I would like to loop an array for a specific set of characters that is constantly changing. From there on I want to toggle case the letters, and I've been told to use this specific code but I can't get it to work. The code MUST loop through an array of characters, where the characters are coming from an "input" textbox. How can I fix this?
I should mention that I'm doing this for class in high school, so I'm no where near perfect at coding.
<html>
<head>
<script type="text/javascript">
function toggleCase() {
var i = document.getElementById("input").value.length;
var word = document.getElementById("input").value;
var chop =new array(i);
for (a=i; a <= i; a++) {
character[i] = word.slice(i-1,i)
if (character[i] == character[i].toUpperCase;){
character[i] = character[i].toLowerCase();
}
else {
character[i] = character[i].toUpperCase();
}
}
var final
for (a=i; a <= i; a++) {
final += character[i];
}
document.getElementById("output").value = final
}
</script>
</head>
<body>
<p>Enter letters for conversion:</p>
<form>
<input type="text" name="input" id="input" value="sample" maxlength="10"><br />
<input type="text" name="output" id="output" value="" /> <br/>
<input type="checkbox" name="toggle" value="ToggleCase" onClick="toggleCase(this.form)">Toggle Case<br/>
</form>
</body>
</html>
Maybe you should take a look at some api's and howtos but here is your code:
<html>
<head>
<script type="text/javascript">
function toggleCase() {
var text = document.getElementById("input").value;
var character = new Array(text.length);
for (i=0, a = text.length; i < a; i++) {
character[i] = text[i];
if (character[i] == character[i].toUpperCase){
character[i] = character[i].toLowerCase();
}
else {
character[i] = character[i].toUpperCase();
}
}
document.getElementById("output").value = character.join('');
}
</script>
</head>
<body>
<p>Enter letters for conversion:</p>
<form>
<input type="text" name="input" id="input" value="sample" maxlength="10"><br />
<input type="text" name="output" id="output" value="" /> <br/>
<input type="checkbox" name="toggle" value="ToggleCase" onClick="toggleCase()">Toggle Case<br/>
</form>
</body>
</html>
function toggleCase() {
var str = document.getElementById("input").value;
for (var i=0; i<str.length; i++) {
str[i] = (str[i]==str[i].toUpperCase() ? str[i].toLowerCase() : str[i].toUpperCase());
}
document.getElementById("output").value = str;
}
that's a for loop that does the job. and remember .toUpperCase and .toLowerCase are functions
You might want to take a look at the String's split method.
var str = 'foo bar baz';
The simplest way to convert a string into a char array is by passing an empty string into the split method.
var charArray = str.split(''):
// charArray === ['f','o','o' ... 'b','a','z'];
Also a FYI, passing a space character into split will give you an array of words.
var wordArray = str.split(' ');
// wordArray === ['foo', 'bar', 'baz'];
I'm a little unclear what you have to solve but it looks like you want a function convert upper case letter into lowercase letters and vise versa.
var userInput = document.getElementById('someTextBox');
// If you want to be fancy you could use JQuery
// var userInput = $(#someTextBox').value()
function toggledCase( str ) {
var characters = str.split('');
// The split method still uses iteration so should be able to say it
// satisfies the argument of looping through each character.
// Split just provides a good abstraction to interface with.
var toggledCharacters = [];
var i;
var ch;
for( i in characters ) {
// For in loops on strings will return the indexes instead
// of the characters
ch = characters[i];
if( ch.toUpperCase() === ch ){
toggledCharacters.push( ch.toLowerCase() );
} else {
toggledCharacters.push( ch.toUpperCase() );
}
// If you like one-liners,
// the conditional if statement could be replace with a ternay statement.
// toggledCharacters.push( ( ch.toUpperCase() === ch ) ?
// ch.toLowerCase() : ch.toUpperCase();
}
return toggledCharacters;
}
My toggledCharacters method only returns an array of characters, so if you want back as a string you could make a for loop;
var arr = toggledCharacters('Foo'); // str = 'fOO';
var str = '';
var i, ch;
for ( i in arr ) {
str += arr[i]; // += is just a short hand notation of saying
// str = str + arr[i];
}
If you are lazy and like one-liners, take a look at functional programming. It's kinda out of scope since you are still in High School.
var arr = toggledCharacters('Foo'); // str = 'fOO';
var str = arr.reduce( function(str, ch) {
return str + ch;
} );
Anyway, this looks a lot cleaner to me than what the teacher outlined.
function toggledCharacters(input) {
input = input.split('');
var output = [];
var i, ch;
for( i in input ) {
output.push( ( input[i].toUpper() === input[i] ) ?
input[i].toLower() : input[i].toUpper()
);
}
return output.reduce(
function(str, ch) {
return str + ch;
}
);
}
Edit:
Oh, I just notice that nowhere in that code the is the check's box boolean value being evaluated.
var checkBox = document.getElementByName('toggle');
var inputTextBox = document.getElementById('input');
var outputTextBox = document.getElementById('output');
var result = inputTextBox.value;
if( checkBox.checked ) {
result = toggleCase( result );
}
outputTextBox.value = result;
Oh another FYI since you are a beginner. Make sure you know to use the browser's console.
If you are on Firefox, grab the firebug app.
Chrome, press Ctrl-Shift-C.
IE has one as well, I just don't care to ever use it.
The console makes it easier to experiment with JS then compared to making html demo page and assuming the code is working as it should.
Plus, these developer tools can show you underlying methods of an object. It makes for a great and quick way to learn JS.

Categories

Resources