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!
Related
I am having a little issue with my JS code.
I have written the below but i cant seem to add spaces between the words?
var textareas = document.getElementsByTagName("textarea");
var values = textareas [0].value ;
var vals = values.s
var result = ""
for (i = 0 ; i < vals. length ; i ++ ) {
if (vals [i] == '') {
}
}
textareas[1].value = result;
as you can see that there are spaces between the numbers which would need to match the word spacings?
the text area is a HTML element, and i want to add spaces between the words so it pastes
this them their
instead of
thisthemtheir in the text area
Thanks
One thing is that if you have spaces in the source text (i.e. between the numbers), you need a space in the comparison. So, it should be:
if (vals [i] == ' ')
and not
if (vals [i] == '')
Also, change the line:
result += [ ]
to read
result += ' '
Here it is working with spaces:
var values = "42,54,53,43, ,42,54,57,49" ;
var vals = values.split(",");
var result = ""
for (i = 0 ; i < vals. length ; i ++ ) {
if (vals [i] == ' ') {
result += ' '
} else {
result += String.fromCharCode (31 + 127 - parseInt (vals [i]));
}
}
console.log(result);
Without using the split reverse and join functions, how would one do such a thing?
The Problem Given: Reverse the words in a string
Sample Input: "Hello World"
Sample Output: "World Hello"
<script>
var newString = "";
var theString = prompt("Enter a Phrase that you would like to reverse (Ex. Hello world)");
newString = theString.split(" ").reverse().join(" ")
document.write(newString);
</script>
Arrays can be used like stacks out of the box. And stacks are LIFO, which is what you need.
function reverseWords(str) {
var word, words, reverse;
words = str.match(/(?:\w+)/g);
reverse = '';
while(word = words.pop()) {
reverse += word + ' ';
}
return reverse.trim();
}
reverseWords('hello world');
Or use the call stack as your stack:
function reverseWords(str) {
var result = '';
(function readWord(i = 0) {
var word = '';
if(i > str.length) {
return '';
}
while(str[i] !== ' ' && i < str.length) {
word += str[i];
i++;
}
readWord(++i); // Skip over delimiter.
result += word + ' ';
}());
return result.trim();
}
reverseWords('hello world');
Another idea for reversing the words in a String is using a Stack data structure. Like so:
var newString = "";
var theString = prompt("Enter a Phrase that you would like to reverse (Ex. Hello world)");
var word = "";
var c;
var stack = [];
for (var i = 0, len = theString.length; i < len; i++) {
c = theString[i];
word += c;
if (c == " " || i == (len-1)) {
word = word.trim();
stack.push(word);
word = "";
}
}
while (s = stack.pop()) {
newString += s + " ";
}
console.log(newString);
You could also go fancy and try something like this:
I couldn't come up with a shorter solution.
var newString = "";
var theString = prompt("Enter a Phrase that you would like to reverse (Ex. Hello world)");
theString.replace(/[^\s]*/g, function (value) {
newString = value + ' ' + newString;
});
document.write(newString);
Of the millions of different solutions, the least amount of typing I could come up with involves using lastIndexOf and substring.
var str = "The quick brown fox",
reversed = "",
idx;
while(true) {
idx = str.lastIndexOf(" ")
reversed = reversed + str.substring(idx).trim() + " "
if (idx < 0) break;
str = str.substring(0, idx)
}
reversed.trim() # Oh, yes, trim too
Output:
"fox brown quick The"
The simplest way to do in javascript. Here replace() have /,/g it will replace all comma from the string to space.
var msg = 'Hello world I am Programmer';
var newstr = msg.split(" ").reverse().join().replace(/,/g, ' ');
console.log(newstr)
;
What I need to do is make this function to where it splits each part of the string entered, and then puts pig latin on each word, meaning it adds ay at the end of each word. Here's what I have so far:
function pigLatin(whatWeTitle) {
var alertThis = " ";
var splitArray = whatWeTitle.split(" ");
for ( i = 0; i < splitArray.length; i++) {
alertThis = makeSentenceCase(splitArray[i]) + " ";
var newWord3 = splitArray.substring(1, whatWeTitle.length) + newWord + 'ay';
alert(newWord3);
}
}
Right now, it just takes the first letter of the string and adds it to the end. It doesn't change each word to pig latin, just the whole phrase. I was wondering of anyone could help me with this. THanks.
You need to use [i] to get items of your array :
var word = splitArray[i];
var newWord3 = word.substring(1,word.length) + word[0] + 'ay';
The best, if you want to end up with the whole new sentence, is to change each word an join them at the end :
var splitArray = whatWeTitle.split(" ");
for ( i = 0; i < splitArray.length; i++) {
var word = splitArray[i];
splitArray[i] = word.substring(1,word.length) + word[0] + 'ay';
}
var newSentence = splitArray.join(' ');
alert(newSentence);
If you test a little, you'll see this algorithm doesn't like the dots or comma in your sentence. If you want something stronger, you'd need a regular expression, for example like this :
var newSentence = whatWeTitle.replace(/[^\. ,]+/g, function(word){
return word.slice(1) + word[0] + 'ay';
});
alert(newSentence);
This works by replacing in place the words in the text, using a function to transform each word.
Something like this ?
function pigLatin(whatWeTitle) {
var alertThis = " ";
var splitArray = whatWeTitle.split(" ");
var finalString = "";
for ( i = 0; i < splitArray.length; i++) {
finalString += splitArray[i]+ "ay ";
}
alert(finalString);
}
pigLatin("this is a test");
You probably want to split off the first consonant values and then append them along with 'ay'.
I would use a regex to accomplish this. Here is a JSFiddle showing an example.
First part is split the word
var words = text.split(" ");
Next part is to piglatinify™ each word
words = words.map(function(word){ return pigLatinifyWord(word);});
This is the piglatinify™ function
function pigLatinifyWord(word){
var result;
var specialMatches = word.match(/(\W|\D)+$/);
var specialChars;
if(specialMatches && specialMatches.length >= 0){
var specialIndex = word.indexOf(specialMatches[0]);
specialChars = word.slice(specialIndex);
word = word.substr(0, specialIndex);
}
var i = word.search(/^[^aeiou]/);
if(i >= 0){
result = word.slice(i+1) + word.slice(0, i+1) + "ay";
}
else{
result = word + "ay";
}
if(specialChars){
result += specialChars;
}
return result;
}
Update
JSFiddle example now includes handling for non-word non-digit characters
I have a string. It's just like;
var str = "This is an example sentence, thanks.";
I want to change every fifth element of this string.
for(var i=5; i<=str.length; i=i+5)
{
str[i]='X'; // it doesn't work, I need something like that
}
So I want str to be "ThisXis aX exaXple XenteXce, XhankX."
Is there any way to do that?
Use RegEx
str = str.replace(/(....)./g, "$1X")
jsfiddle
var str = "This is an example sentence, thanks.";
var newString = "";
for(var i=0; i<str.length; i++)
{
if ((i % 5) == 4) {
newString += "X";
} else {
newString += str.charAt(i);
}
}
Here is a running example. http://jsfiddle.net/WufuK/1
You could use a map, although the regex solution looks better.
str = str.split('').map(function(chr, index){
return (index % 5 === 4)? 'X' : chr;
}).join('');
You can use string.substring()
var a = "This is an example sentence, thanks.";
var result ="";
for(var i=0;i <a.length-1; i+=5){
result +=a.substr(i, 4)+'X';
}
alert(result)
jsFiddle: http://jsfiddle.net/mVb4u/5
This approach uses Array.reduce, which is native to JavaScript 1.8, but can be backported.
Array.prototype.reduce.call("This is an example sentence, thanks.", function(p,c,i,a) { return p + ( i % 5 == 4 ? "X" : c); });
Update: Updated to reflect am not i am's comments below.
I'm wondering if there's a way to count the words inside a div for example. Say we have a div like so:
<div id="content">
hello how are you?
</div>
Then have the JS function return an integer of 4.
Is this possible? I have done this with form elements but can't seem to do it for non-form ones.
Any ideas?
g
If you know that the DIV is only going to have text in it, you can KISS:
var count = document.getElementById('content').innerHTML.split(' ').length;
If the div can have HTML tags in it, you're going to have to traverse its children looking for text nodes:
function get_text(el) {
ret = "";
var length = el.childNodes.length;
for(var i = 0; i < length; i++) {
var node = el.childNodes[i];
if(node.nodeType != 8) {
ret += node.nodeType != 1 ? node.nodeValue : get_text(node);
}
}
return ret;
}
var words = get_text(document.getElementById('content'));
var count = words.split(' ').length;
This is the same logic that the jQuery library uses to achieve the effect of its text() function. jQuery is a pretty awesome library that in this case is not necessary. However, if you find yourself doing a lot of DOM manipulation or AJAX then you might want to check it out.
EDIT:
As noted by Gumbo in the comments, the way we are splitting the strings above would count two consecutive spaces as a word. If you expect that sort of thing (and even if you don't) it's probably best to avoid it by splitting on a regular expression instead of on a simple space character. Keeping that in mind, instead of doing the above split, you should do something like this:
var count = words.split(/\s+/).length;
The only difference being on what we're passing to the split function.
Paolo Bergantino's second solution is incorrect for empty strings or strings that begin or end with whitespaces. Here's the fix:
var count = !s ? 0 : (s.split(/^\s+$/).length === 2 ? 0 : 2 +
s.split(/\s+/).length - s.split(/^\s+/).length - s.split(/\s+$/).length);
Explanation: If the string is empty, there are zero words; If the string has only whitespaces, there are zero words; Else, count the number of whitespace groups without the ones from the beginning and the end of the string.
string_var.match(/[^\s]+/g).length
seems like it's a better method than
string_var.split(/\s+/).length
At least it won't count "word " as 2 words -- ['word'] rather than ['word', '']. And it doesn't really require any funny add-on logic.
Or just use Countable.js to do the hard job ;)
document.deepText= function(hoo){
var A= [];
if(hoo){
hoo= hoo.firstChild;
while(hoo!= null){
if(hoo.nodeType== 3){
A[A.length]= hoo.data;
}
else A= A.concat(arguments.callee(hoo));
hoo= hoo.nextSibling;
}
}
return A;
}
I'd be fairly strict about what a word is-
function countwords(hoo){
var text= document.deepText(hoo).join(' ');
return text.match(/[A-Za-z\'\-]+/g).length;
}
alert(countwords(document.body))
Or you can do this:
function CountWords (this_field, show_word_count, show_char_count) {
if (show_word_count == null) {
show_word_count = true;
}
if (show_char_count == null) {
show_char_count = false;
}
var char_count = this_field.value.length;
var fullStr = this_field.value + " ";
var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi;
var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, "");
var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi;
var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " ");
var splitString = cleanedStr.split(" ");
var word_count = splitString.length -1;
if (fullStr.length <2) {
word_count = 0;
}
if (word_count == 1) {
wordOrWords = " word";
} else {
wordOrWords = " words";
}
if (char_count == 1) {
charOrChars = " character";
} else {
charOrChars = " characters";
}
if (show_word_count & show_char_count) {
alert ("Word Count:\n" + " " + word_count + wordOrWords + "\n" + " " + char_count + charOrChars);
} else {
if (show_word_count) {
alert ("Word Count: " + word_count + wordOrWords);
} else {
if (show_char_count) {
alert ("Character Count: " + char_count + charOrChars);
}
}
}
return word_count;
}
The get_text function in Paolo Bergantino's answer didn't work properly for me when two child nodes have no space between them. eg <h1>heading</h1><p>paragraph</p> would be returned as headingparagraph (notice lack of space between the words). So prepending a space to the nodeValue fixes this. But it introduces a space at the front of the text but I found a word count function that trims it off (plus it uses several regexps to ensure it counts words only). Word count and edited get_text functions below:
function get_text(el) {
ret = "";
var length = el.childNodes.length;
for(var i = 0; i < length; i++) {
var node = el.childNodes[i];
if(node.nodeType != 8) {
ret += node.nodeType != 1 ? ' '+node.nodeValue : get_text(node);
}
}
return ret;
}
function wordCount(fullStr) {
if (fullStr.length == 0) {
return 0;
} else {
fullStr = fullStr.replace(/\r+/g, " ");
fullStr = fullStr.replace(/\n+/g, " ");
fullStr = fullStr.replace(/[^A-Za-z0-9 ]+/gi, "");
fullStr = fullStr.replace(/^\s+/, "");
fullStr = fullStr.replace(/\s+$/, "");
fullStr = fullStr.replace(/\s+/gi, " ");
var splitString = fullStr.split(" ");
return splitString.length;
}
}
EDIT
kennebec's word counter is really good. But the one I've found includes a number as a word which is what I needed. Still, that's easy to add to kennebec's. But kennebec's text retrieval function will have the same problem.
This should account for preceding & trailing whitespaces
const wordCount = document.querySelector('#content').innerText.trim().split(/\s+/).length;
string_var.match(/[^\s]+/g).length - 1;