Get an array of matches in string as indexes - javascript

Example: "abc abc ab a".indexOfList("abc") returns [0,4]
My code:
String.prototype.indexOfList=function(word){
var l=[];
for(var i=0;i<this.length;i++){ //For each character
var pushed=(this[i]==word[0])&&(word.length+i<=this.length);
if (pushed) {
for(var j=1;j<word.length;j++){
if (word[j]!=this[i+j]) {
pushed=false; break;
}
}
}
if (pushed) {
l.push(i);
}
}
return l;
}
Is there a better and smaller way than this?

You can use the regex match command:
var re = /abc/g,
str = "abc abc ab a";
var pos = [];
while ((match = re.exec(str)) != null) {
pos.push(match.index);
}

There's a version that could handle overlapping strings, i.e. pattern aaa for a string aaaaa should return [0,1,2].
function indexOfList(needle, haystack) {
const result = [];
let i = 0;
while (haystack.includes(needle, i)) {
const match = haystack.indexOf(needle, i);
result.push(match);
i = match + 1;
}
return result;
}
indexOfList("abc", "abc abc ab a"), // [0, 4]
indexOfList("aaa", "aaaabc abc ab a") // [0, 1]
I would also advice against extending the prototype of a native object. It could lead to a very nasty name clashes.
Consider your collegue (or even a language maintainer) adds a function with the same name.

With indexOf function
var str = "abc abc ab a";
var i = -1;
var result = [];
while (true) {
i = str.indexOf("abc", i + 1);
if (i == -1) break;
result.push(i);
}
document.write(result);

No need to complicate things. A very similar method to this already exists: String.indexOf.
You can also pass a second parameter to this method, telling it where to start looking. If you keep increasing this second parameter, you can quickly find each occurrence.
String.prototype.indexOfList = function(word) {
var start = this.indexOf(word);
var l = [start]
if(start == -1) {
return [-1, -1];
}
var index = start;
for(var i = start + word.length; i < this.length - word.length; i = index) {
index = this.indexOf(word, i);
if(index == -1) {
break;
}
l.push(index);
}
return l;
}
This will start at the first occurrence, and continue to add on each index the word appears at.

you can use replace
String.prototype.indexOfList = function(word){
var l=[];
this.replace(new RegExp(word,"g"), (a,i) => l.push(i));
return l;
}
console.log("abc abc ab a".indexOfList("abc"));

Related

Reverse words(not letters) for a string without using .reverse()

The problem I am working on asks for me to write a function reverseMessage() that takes a string message and reverses the order of the words in place.
The answer I first came up with works but apparently doesn't meet the requirements of this task:
function reverseMessage(string) {
return string.split(" ").reverse().join(" ");
}
For example:
var string = "reversed are string your in words the now"
var results = "now the words in your string are reversed"
New solution:
I would like to split this string into an array and then loop through that array and swap the 1st index with the last index, the 2nd index with second to last index, 3rd index with the 3rd to last index, etc... until I meet in the middle.
I am trying to make the two different functions below work:
function reverseMessage(string) {
var array = string.split(" ");
//loop through array and replace first index with last index, second
index with second to last index, third index with third to last index, etc
for (var i = 0; i < array.length/2; i++) {
for (var j = (array.length-1); j > array.length/2; j--) {
array[i] = array[j];
array[j] = array[i];
messageSplit.join(",");
}
};
function reverseMessage2(string) {
var array = string.split(" ");
var newArray = []
for (var i = 0; i < array.length/2; i++) {
newArray.unshift(array[i]++);
newArray.join(",");
return newArray;
}
};
Am I on the right track?
function reverseMessage(string) {
var array = string.split(" ");
var result="";
for (var i = array.length-1; i >=0; i--) {
result+=array[i]+" ";
}
console.log(result);
};
So in yours reverseMessage function You are trying to swap variable for that you are doing
array[i] = array[j];
array[j] = array[i];
Which is giving array[i]=array[j] so let say array[i]="This" and array[j]="That"so according to yours code array[i] will be "That" and array[j] will also be "That" so you can try something like this:
function reverseMessage(string) {
var array = string.split(" ");
//loop through array and replace first index with last index, second
//index with second to last index, third index with third to last index, etc
for (var i = 0,j=(array.length)-1; i < array.length/2; i++) {
temp=array[i]
array[i] = array[j];
array[j]=array[i]
array[j] = temp; j--;}
console.log(array.join(" "));
}; reverseMessage("find you will pain only go you recordings security the into if");
try this one
function reverseMessage( str ) {
var arrStr = [];
var temp ="";
for(var i = 0 ; i < str.length ; i++)
{
if(str[i] === " ")
{
arrStr.push(temp);
temp="";
}
else
{
temp += str[i];
}
}
if(temp.length >= 0)
{
arrStr.push(temp);
}
var result = "";
for(var x=arrStr.length-1 ; x >=0 ; x--)
{
result += " "+arrStr[x];
}
return result;
}
console.log(reverseMessage("I am here"));
Well, someone's gotta do it:
function rev(s){
var a = s.split(/ /),
l = a.length;
i = l/2 | 0;
while (i--) a.splice(i, 1, a.splice(l-1-i, 1, a[i])[0]);
return a.join(' ');
}
document.write(rev('0 1 2 3 4 5 6 7 8 9'));
Using Array.split(), Array.pop(), Array.push() and String.substr():
var flip = function(str) {
var res = "", sp = " ", arr = str.split(sp);
while (arr.length)
res += arr.pop() + sp;
return res.substr(0, res.length - 1); //remove last space
};
alert(flip("reversed are string your in words the now"));
Using String.lastIndexOf() and String.substr():
var flip = function(str) {
var res = "", i, sp = ' ';
while (str) {
i = str.lastIndexOf(sp);
res += str.substr(i + 1) + sp;
str = str.substr(0, i);
}
return res.substr(0, res.length - 1); //remove last space
};
alert(flip("reversed are string your in words the now"));
What you want to do is split the words message into individual strings reverse them and then add them together, that will reverse them in place. Try
function reverseMessage(message){
var reversedMessage = ''; //A string to hold the reversed message
var words = message.split(' ');
for(var i =0; i< words.length; i++){
reversedMessage += reverse(words[i]) + " ";// add the reversed word to the reversed message, with a space at the end so the words dont touch
}
return reversedMessage
}
//A helper function that reverses a string
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
sources: http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
with `pop()` ;)
function reverseMessage(string) {
var array = string.split(" ");
var result="";
while (array.length > 0) {
result += array.pop()+" ";
}
console.log(result);
};

Capture non-adjacent repeating letters

How do I capture repeating letters in a word like abababa = 2matches( a and b is repeating )
I know how to do it when the letters are adjacent like so /(\w)\1+/ .
Thanks
Try to use this String expansion:
String.prototype.getRepeating = function() {
var length = this.length;
var found = '';
var repeating = '';
var index;
var letter;
for (index = 0; index < length; index++) {
letter = this.charAt(index);
if (-1 == found.indexOf(letter)) {
found = found.concat(letter);
} else {
if (-1 == repeating.indexOf(letter)) {
repeating = repeating.concat(letter);
}
}
}
return repeating;
}
The tests:
var tests = ['ab', 'aa', 'bb', 'abab', 'abb', 'aab', 'bab'];
for (var index in tests) {
console.log(tests[index], '=>', tests[index].getRepeating());
}
ab => (an empty string)
aa => a
bb => b
abab => ab
abb => b
aab => a
bab => b
If I understand correctly, you want to extract letters which appear more than once in a given word. If so, you simply need to iterate over the letters of the word, accumulate their occurrence, then filter out letters which only appear once.
var testString = "abababa";
var letters = countGroupByLetter(testString);
var result = filterMap(letters, function(v) {
return v > 1;
});
console.log(result);
function countGroupByLetter(testString) {
var result = {};
for (var ii = 0; ii < testString.length; ii++) {
var letter = testString.charAt(ii);
if (result[letter]) {
result[letter] ++;
} else {
result[letter] = 1;
}
}
return result;
}
function filterMap(map, filterFunction) {
var result = {};
for (var p in map) {
if (filterFunction(map[p])) {
result[p] = map[p];
}
}
return result;
}
Since you already know about back references, I suppose that you know you can find out if there is a letter repetition in a string, using /(\w).*\1/. Capturing all repetitions in one pass would not be possible though, you'd still need to execute a pattern repeatedly and accumulate the matched characters (for instance using /(\w)(?=.*\1)/g). That, however, would not be optimal.
var repeatingLetters = /(\w)(?=.*\1)/g;
var testString = "abababa";
var captures = null;
var result = {};
while ((captures = repeatingLetters.exec(testString)) != null) {
result[captures[1]] = true;
}
console.log(result);

Returning multiple index values from an array using Javascript

I have an array containing the individual letters of a word and i want to search the array to return the index values of certain letters. However, if the word contains more a letter more than once (such as 'tree') the programme only returns one index value.
This is a sample of the code:
var chosenWord = "tree";
var individualLetters = chosenWord.split('');
var isLetterThere = individualLetters.indexOf(e);
console.log(isLetterThere);
this code will return the number '2', as that is the first instance of the letter 'e'. How would i get it to return 2 and 3 in the integer format, so that i could use them to replace items in another array using the .splice function.
indexOf takes a second parameter, as the position where it should start searching from.
So my approach would be:
function findLetterPositions(text, letter) {
var positions = new Array(),
pos = -1;
while ((pos = text.indexOf(letter, pos + 1)) != -1) {
positions.push(pos);
}
return positions;
}
console.log(findLetterPositions("Some eerie eels in every ensemble.", "e"));
http://jsfiddle.net/h2s7hk1r/
You could write a function like this:
function indexesOf(myWord, myLetter)
{
var indexes = new Array();
for(var i = 0; i < myWord.length; i++)
{
if(myWord.charAt(i) == myLetter)
{
indexes.push(i);
}
}
return indexes;
}
console.log(indexesOf("tree", "e"));
Loop through it as here:
var chosenWord = "tree";
var specifiedLetter = "e";
var individualLetters = chosenWord.split('');
var matches = [];
for(i = 0;i<individualLetters.length;i++){
if(individualLetters[i] == specifiedLetter)
matches[matches.length] = i;
}
console.log(matches);
An alternative using string methods.
var str = "thisisasimpleinput";
var cpy = str;
var indexes = [];
var n = -1;
for (var i = cpy.indexOf('i'); i > -1; i = cpy.indexOf('i')) {
n += i;
n++;
indexes.push(n);
cpy = cpy.slice(++i);
}
alert(indexes.toString());
var getLetterIndexes = function(word, letter) {
var indexes = [];
word.split("").forEach(function(el, i) {
el === letter && indexes.push(i);
});
return indexes;
};
getLetterIndexes("tree", "e"); // [2, 3]

Returning a string with only vowels capitalized

I'd like to return the variable newString with only vowels capitalized. Not sure how to proceed. Tried using an if/else block but my logic wasn't correct.
function LetterChanges(str) {
var newArray = [];
for (var i = 0; i < str.length; i++) {
var strCode = str.charCodeAt(i) + 1;
var strLetter = String.fromCharCode(strCode);
newArray.push(strLetter);
var newString = newArray.join("");
}
return newString;
}
LetterChanges("hello");
This is different from your approach, but you can do this:
function LetterChanges(str) {
return str.toLowerCase().replace(/[aeiou]/g, function(l) {
return l.toUpperCase();
});
}
console.log(LetterChanges("The Quick Brown Fox Jumped Over The Lazy Dog"));
Here's an approach that's closer to your attempt and uses somewhat simpler concepts:
function LetterChanges(str) {
var newArray = [];
for (var i = 0; i < str.length; i++) {
var ch = str.charAt(i);
if ('aeiouAEIOU'.indexOf(ch) !== -1) {
newArray.push(ch.toUpperCase());
} else {
newArray.push(ch.toLowerCase());
}
}
return newArray.join("");
}
Split, map, join.
var vowels = 'aeiou';
var text = 'my random text with inevitable vowels';
var res = text.split('').map(function(c){
return (vowels.indexOf(c) > -1) ? c.toUpperCase() : c;
});
See the fiddle: http://jsfiddle.net/zo6j89wv/1/
Strings are Collections of word-characters, so you can directly access each part of the string:
var foo = 'bar';
console.log(foo[0]); // outputs 'b'
Hence you can extend this to uppercase the output:
console.log(foo[0].toUpperCase() // outputs 'B'
To do this without regex, you can set the string to lower case, then iterate once over, calling toUpperCase() on each vowel.
function letterChanges(string){
var vowels = 'aeiou';
var lowerString = string.toLowerCase();
var result = '';
for( var i=0; i<lowerString.length; i++){
if( vowels.indexOf( lowerString[i] ) >= 0 ){ //if lowerString[i] is a vowel
result += lowerString[i].toUpperCase();
} else {
result += lowerString[i]
}
}
return result;
}
const vowelSound = string => {
let res = string.split("").filter(item => item === 'a' || item === 'i' || item === 'e' || item === 'o' || item === 'u')
return res.join("")
}

Is there any pre-built method for finding all permutations of a given string in JavaScript?

I'm a newbie to the JavaScript world. As the title mentions, I want to know whether there is any pre-built method in JavaScript to find all possible permutations of a given string.
For example, given the input:
the
Desired output:
the
teh
eht
eth
het
hte
//string permutation
function permutation(start, string) {
//base case
if ( string.length == 1 ) {
return [ start + string ];
} else {
var returnResult = [];
for (var i=0; i < string.length; i++) {
var result = permutation (string[i], string.substr(0, i) + string.substr(i+1));
for (var j=0; j<result.length; j++) {
returnResult.push(start + result[j]);
}
}
return returnResult;
}
}
permutation('','123') will return
["123", "132", "213", "231", "312", "321"]
function permutations(str){
if (str.length === 1) {
return str;
}
var permut = [];
for (var i=0; i<str.length; i++){
var s = str[0];
var _new = permutations(str.slice(1, str.length));
for(var j=0; j<_new.length; j++) {
permut.push(s + _new[j]);
}
str = str.substr(1, str.length -1) + s;
}
return permut;
}
permutations('the');
//output returns:[ 'the', 'teh', 'het', 'hte', 'eth', 'eht' ]
No pre-built, but writing such function is possible.. here is one relatively simple way using two functions:
function FindAllPermutations(str, index, buffer) {
if (typeof str == "string")
str = str.split("");
if (typeof index == "undefined")
index = 0;
if (typeof buffer == "undefined")
buffer = [];
if (index >= str.length)
return buffer;
for (var i = index; i < str.length; i++)
buffer.push(ToggleLetters(str, index, i));
return FindAllPermutations(str, index + 1, buffer);
}
function ToggleLetters(str, index1, index2) {
if (index1 != index2) {
var temp = str[index1];
str[index1] = str[index2];
str[index2] = temp;
}
return str.join("");
}
Usage:
var arrAllPermutations = FindAllPermutations("the");
Live test case: http://jsfiddle.net/yahavbr/X79vz/1/
This is just basic implementation, it won't remove duplicates and has no optimization. However for small strings you won't have any problem, add time measure like in the above test case and see what's your reasonable limit.
This is similar but finds all anagrams/permutations from an array of words. I had this question in an interview. Given an array of words ['cat', 'dog', 'tac', 'god', 'act'], return an array with all the anagrams grouped together. Makes sure the anagrams are unique.
var arr = ['cat', 'dog', 'tac', 'god', 'act'];
var allAnagrams = function(arr) {
var anagrams = {};
arr.forEach(function(str) {
var recurse = function(ana, str) {
if (str === '')
anagrams[ana] = 1;
for (var i = 0; i < str.length; i++)
recurse(ana + str[i], str.slice(0, i) + str.slice(i + 1));
};
recurse('', str);
});
return Object.keys(anagrams);
}
console.log(allAnagrams(arr));
//["cat", "cta", "act", "atc", "tca", "tac", "dog", "dgo", "odg", "ogd", "gdo", "god"]
Assuming a large string to search, you could use a regular expression
to examine a set of possibles that first matches the letters and the total number of letters,
and return the matches that use the same letter set as the pattern.
//(case-insensitive)
function lettersets(str, pat){
var A= [], M, tem,
rx= RegExp('\\b(['+pat+']{'+pat.length+'})\\b', 'gi'),
pattern= pat.toLowerCase().split('').sort().join('');
while((M= rx.exec(str))!= null){
tem= M[1].toLowerCase().split('').sort();
if(tem.join('')=== pattern) A.push(M[1]);
};
return A;
}
lettersets(s, 'the').sort();
function swap(a, b, str) {
if (a == b)
str = str;
else {
str = str.split("");
var temp = str[a];
str[a] = str[b];
str[b] = temp;
str = str.join("");
}
}
function anagram(a1, b1, ar) {
if (a1 == b1)
document.write(ar + "<br/>");
else
for (i = a1; i < b1; i++) {
swap(a1, b1, ar);
anagram((a1) ++, b1, ar);
swap(a1, b1, ar);
}
}
Well there isnt any built in function in js(i dont believe it to be in any coding language)......and anyways this is the fully functioning program, it omits any repetitions and also displays the number of permutations.....
var n=0;
var counter=0;
var storarr=new Array();
function swap(a,b,str) { //swaps the terms str[a] and str[b] and returns the final str
str = str.split("");
var temp = str[a];
str[a] = str[b];
str[b] = temp;
return str.join("");
}
function anagram(_a,_b,ar) { //actual function which produces the anagrams
if(_a == _b) {
storarr[n]=ar;
n++;
counter++;
}
else {
for(var i= _a;i<= _b;i++) {
ar=swap(_a,i,ar);
anagram(_a+1,_b,ar);
ar=swap(_a,i,ar);
}
}
}
function factorial(a) { //return a!
var x=1;
for(var i=1;i<=a;i++)
x=x*i;
return x;
}
var strl=prompt("Enter String:","");
var l=strl.length;
anagram(0,l-1,strl);
storarr.sort(); //sorts the storarr alphabetically
var storlen=storarr.length;
var cai=0;
var counterarr = new Array();
strl.split("");
for(var i=0;i<l;i=i+c) { //determines the number of times a term is repeating
var c=1;
for(var j=i+1;j<l;j++) {
if(strl[i]==strl[j])
c++;
}
counterarr[cai]=c;
cai++;
}
var yellow=1;
for(var i=0;i<counterarr.length;i++) { //multiplies the terms of the counter array
yellow=yellow*factorial(counterarr[i]);
}
counter=counter/yellow;
document.write("Count : " + counter + "<br />");
for(var i=0;i<storlen;i=i+yellow) { //prints the non-flagged terms in storarr
document.write(storarr[i] + "<br />");
}
strl.join("");
<pre>
<script>
var count = 0;
var duplicate = false;
function FindAllPermutations(str, index) {
for (var i = index; i < str.length; i++) {
var newstr;
if (index == i) newstr = str;
else newstr = SwapLetters(str, index, i);
if (!duplicate) {
count++;
document.write(newstr + "\n");
if (i == index) duplicate = true;
} else if (i != index) duplicate = false;
FindAllPermutations(newstr, index + 1);
}
}
function SwapLetters(str, index1, index2) {
if (index1 == index2) return str;
str = str.split("");
var temp = str[index1];
str[index1] = str[index2];
str[index2] = temp;
return str.join("");
}
FindAllPermutations("ABCD", 0); // will output all 24 permutations with no duplicates
document.write("Count: " + count);
</script>

Categories