I would like to search in javascript string and get all string occurrence by word index for example:
var str = 'Hello this is my this is world'
myFindWordIndex(str, 'this is') ==> [1, 4]
(two occurrences of the search string, one starts at word index 1 and one starts at index 4)
the solution can use JQuery
I would split the phrase you're trying to find and where you're trying to find it into words. Then simply check if the phrase contains each piece of the search phrase.
function check(hay, needle, from) {
var i = 1;
while (i < needle.length) {
if (hay[from] != needle[i])
return false;
i++;
from++;
}
return true;
}
function myFindWordIndex(str, findme) {
var indices = [];
var needle = findme.split(" ");
var hay = str.split(" ");
for (var i = 0; i < hay.length - needle.length; i++) {
if (hay[i] == needle[0] && (needle.length==1||check(hay, needle, i)))
indices.push(i);
}
return indices;
}
var str = 'Hello this is my this is world';
console.log(myFindWordIndex(str, 'this is')); // ==> [1, 4]
Here's a clunky solution using Lodash.js.
function run(str, searchingFor) {
return _.flatten(
_.zip(str.split(/\s+/), str.split(/\s+/))
)
.slice(1, -1)
.join(' ')
.match(/\w+\s+\w+/g)
.reduce((a, b, i) => {
return b === searchingFor
? a.concat(i)
: a;
}, []);
}
Here is it running...
run('Hello this is my this is world', 'this is');
// => [1, 4]
Not ideal. Not very portable. But it works.
using function from How to find indices of all occurrences of one string in another in JavaScript? for multi search
function getIndicesOf(searchStr, str, caseSensitive) {
var startIndex = 0, searchStrLen = searchStr.length;
var index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
function myFindWordIndex(str, search_str) {
var res = [];
$.each(getIndicesOf(search_str, str, true), function(i, v) {
res.push(str.slice(0, v).split(' ').length)
});
return res;
}
adding #Mohammad's answer since it looks the cleanest:
var str = 'Hello this is my this is world'
var pos = myFindWordIndex(str, 'this is');
console.log(pos);
function myFindWordIndex(str, word){
var arr = [];
var wordLength = word.split(" ").length;
var position = 0;
str.split(word).slice(0, -1).forEach(function(value, i){
position += value.trim().split(" ").length;
position += i > 0 ? wordLength : 0;
arr.push(position);
});
return arr;
}
Related
I was writing code and came into this problem,
You have a specific string which is in this form:
d ae2 n s
now we have to decode this in a specific way,
Split it into different parts by spaces to make an array like ["d","ae2","n","s"]
Evaluate each element of the array and find out if there is a number in it.
If there is a number then repeat the string the number of times.
Add it into the array and continue.
So the output array should be
["d","ae","ae","n","s"]
I have already tried a lot but got nothing
I have used this code earlier but it ends on the second string:
var str = "d ae2 n s"
var res = str.split(" ");
alert(res.length);
for(var x = 0; x < res.length; x++ ){
var std = res[x];
var fun = checkNum(std);
if(fun === true){
var numbers = str.match(/\d+/g).map(Number);
var index = res.indexOf(std);
var result = std.replace(/[0-9]/g, '');
var res2 = result.repeat(numbers);
res[index] = res2;
}
else{
continue;
}
for(var i = 0; i < res.length; i++ ){
console.log(res[x]);
}
}
function checkNum(t){
return /\d/.test(t);
}
// I am a terible coder :/
expected input : d ae2 n s
expected output : ["d","ae","ae","n","s"]
Using fill() and flatMap() methods and
regex replace
/[^0-9]/ - all non numerical chars
/[0-9]/ - all numerical chars
var str = 'd ae2 n s'
var res = str
.split(' ')
.flatMap(i =>
Array(+i.replace(/[^0-9]/g, '') || 1)
.fill(i.replace(/[0-9]/g, ''))
)
console.log(res)
You can simply loop over your array and populate an other array that will hold your result after checking for a number :
const results = [];
"d ae2 n s".split(' ').forEach(token => {
const match = token.match(/\d+/);
if (match) {
const newStr = token.split(/\d/)[0];
for (let i = 0; i < match[0]; i++) {
results.push(newStr);
}
} else {
results.push(token)
}
})
console.log(results);
You can check Seblor's answer for optimized logic. I have modified your code so that it will be easy for you to understand where you went wrong while doing this. I have added comments to your code where I have changed things:
var str = "d ae2 n s"
var res = str.split(" ");
// create a variable to store the output.
var output = [];
for(var x = 0; x < res.length; x++ ){
var std = res[x];
var fun = checkNum(std);
if(fun === true){
// map returns an array, so take the first element, it will be your number.
var numbers = str.match(/\d+/g).map(Number)[0];
var index = res.indexOf(std);
var result = std.replace(/[0-9]/g, '');
// instead of doing the repeat and updating the current index,
// push the result, i.e. the current string to be repeated "numbers" times into
// the output array.
for (var i = 0; i < numbers; i++) {
output.push(result)
}
}
else{
// if does not contain any number, push the current item to ouput
output.push (std);
continue;
}
}
function checkNum(t){
return /\d/.test(t);
}
console.log(output);
You can do:
const str1 = 'd ae2 n s';
const str2 = 'e d aefg4 m n s';
const regex = /\d+/;
const getResult = input => input.split(' ').reduce((a, c) => {
const n = c.match(regex);
return n
? [...a.concat(c.replace(n, ' ').repeat(n).trim().split(' '))]
: [...a, c];
}, []);
console.log(getResult(str1));
console.log(getResult(str2));
you can use the Array prototype reduce and filter
const input = 'd ae2 n s';
const output = input.split(' ').reduce((memory, current) => {
const numberIndex = current.split('').findIndex(c => !isNaN(c));
const newCurrent = current.split('').filter((_, index) => index !== numberIndex).join('');
if(numberIndex !== -1) {
for(let i = 0; i < parseInt(current[numberIndex]); i++) {
memory.push(newCurrent);
}
} else {
memory.push(current);
}
return memory;
}, []);
console.log(output);
Hope this helped
You can try with following:
let str = "d ae2 n s"
let split = str.split(" ")
let rx = new RegExp("[0-9]")
let res = [];
split.forEach(s => {
if(rx.exec(s) !== null) {
let rxResult = rx.exec(s)
let count = rxResult[0];
let matchIdx = rxResult[1];
for(let i = 0; i < count; i++) {
res.push(s.replace(count, ""))
}
} else {
res.push(s);
}
})
I'm new student in here,sorry for asking simple question and I'm trying to solve a problem to count a same letter.
Input:"aabbcde"
cause a = 2, b= 2, c= 1 , d =1 , e = 1
Output:"2a2b1c1d1e" or a2b2c1d1e1
and here's my code unfinished, I stucked
function repeatL(str) {
var word = str.split("").sort();
var temp = 0;
var i =1;
while(i< word.length){
if(word[i] === word[i +1]) {
//return temp to array of a += 1 ?
};
}
}
repeatL("abbbdd"); //output should be a1b3d2
also what if the input is not string but an array:
Input:[a,ab,bc,d,e]
is that even possible to solved?
You could use a variable for the result string, start with a count variable with 1 and iterate with a check of the former and actual letter. Then either count or move the count to the result set with the last letter. Reset counter to one, because the actual letter count is one.
At the end, finish the result with the last count and the letter, because one letter is not processed with the count (remember, you start with index 1, and you look always to the letter before of the actual index).
function repeatL(str) {
var word = str.split("").sort(),
count = 1,
i = 1,
result = '';
while (i < word.length) {
if (word[i - 1] === word[i]) {
count++;
} else {
result += count + word[i - 1];
count = 1;
}
i++;
}
result += count + word[i - 1];
return result;
}
console.log(repeatL("aabbcde"));
console.log(repeatL(['a', 'ab', 'bc', 'd', 'e'].join(''))); // with array after joining
You can simply use reduce() to build array and then join() to get string.
var input = "aabbcde";
var result = input.split('').reduce(function(r, e) {
var i = r.indexOf(e);
(i != -1) ? r[i - 1] ++: r.push(1, e)
return r;
}, []).join('')
console.log(result)
I'd go with an object and add each character as a key. If the key exists increment the value, else add a new key and with value 1
function repeatL(str) {
var count = {};
var arr = str.split("");
str = "";
for(var i=0;i<arr.length;i++){
if(count[arr[i]]){
count[arr[i]] = count[arr[i]]+1;
}
else {
count[arr[i]] = 1;
}
}
for(var key in count){
str+= key+count[key];
}
return str;
}
Following example also works with arrays:
function getFrequency(string) {
var freq = {};
for (var i=0; i<string.length;i++) {
var character = string[i];
if (freq[character]) {
freq[character]++;
} else {
freq[character] = 1;
}
}
return freq;
};
function repeatL(str) {
var freq = getFrequency(str);
result = '';
for (var k in freq) {
if (freq.hasOwnProperty(k)) {
result += freq[k] + k;
}
}
return result;
};
console.log(repeatL('abbbdd'));
console.log(repeatL('aabbcdeaaabbeedd'));
console.log(repeatL(['a', 'a', 'b', 'a', 'c']));
in fact, i have to treat a Arabic characters in javascript but i want to show you an example of what i want:
i have this char:
var char = "KASSAB";
i want to get an array of chars by replacing the letter "A" in "1" "2" "3" everytime, so if i have 2 letters "A" in one char, it must be like that:
K**1**SS**1**B,K**1**SS**2**B, K**1**SS**3**B, K**2**SS**1**B, K**2**SS**2**B, K**2**SS**3**B, K**3**SS**1**B, K**3**SS**2**B, K**3**SS**3**B
Any suggestions Please :( ?
This can be done using a recursive function, as follows:
var initialInput = 'KASSAB',
replaceables = ['A', 'a', 'á'],
replacements = ['**1**', '**2**', '**3**'];
function indexOfFirstReplaceable(input) {
var firstIndex = input.length;
for (var i in replaceables) {
var index = input.indexOf(replaceables[i]);
if (index !== -1) firstIndex = Math.min(firstIndex, index);
}
return firstIndex < input.length ? firstIndex : -1;
}
function replaceAllAs(input) {
var index = indexOfFirstReplaceable(input);
if (index === -1) return [input] // Nothing to replace
var outputs = [];
for (var i in replacements) {
var nextInput = input.substr(0, index) + replacements[i] + input.substr(index + 1);
outputs = outputs.concat(replaceAllAs(nextInput));
}
return outputs;
}
console.log(replaceAllAs(initialInput));
will output
["K**1**SS**1**B", "K**1**SS**2**B", "K**1**SS**3**B", "K**2**SS**1**B", "K**2**SS**2**B", "K**2**SS**3**B", "K**3**SS**1**B", "K**3**SS**2**B", "K**3**SS**3**B"]
EDIT:
Or if you want to be more functional, using map and reduce:
var initialInput = 'KASSAB',
replaceables = ['A', 'a', 'á'],
replacements = ['**1**', '**2**', '**3**'];
function indexOfFirstReplaceable(input) {
return replaceables.reduce(function (currentMin, replaceable) {
var index = input.indexOf(replaceable);
if (index === -1 || currentMin === -1) return Math.max(index, currentMin);
else return Math.min(currentMin, index);
}, -1);
}
function replaceAllAs(input) {
var index = indexOfFirstReplaceable(input);
if (index === -1) return [input]; // Nothing to replace
var outputs = replacements.map(function (replacement) {
var nextInput = input.substr(0, index) + replacement + input.substr(index + 1);
return replaceAllAs(nextInput)
});
return [].concat.apply([], outputs);
}
console.log(replaceAllAs(initialInput));
EDIT 2:
To accommodate the overlap of replaceables and replacements you need to specify the fromIndex when using indexOf:
var initialInput = 'KASSAB',
replaceables = ['A', 'a', 'á'],
replacements = ['A', 'a', 'á'];
function indexOfFirstReplaceable(input, fromIndex) {
return replaceables.reduce(function (currentMin, replaceable) {
var index = input.indexOf(replaceable, fromIndex);
if (index === -1 || currentMin === -1) return Math.max(index, currentMin);
else return Math.min(currentMin, index);
}, -1);
}
function replaceAllAs(input, fromIndex) {
var index = indexOfFirstReplaceable(input, fromIndex);
if (index === -1) return [input]; // Nothing to replace
var outputs = replacements.map(function (replacement) {
var nextInput = input.substr(0, index) + replacement + input.substr(index + 1);
return replaceAllAs(nextInput, index + 1);
});
return [].concat.apply([], outputs);
}
console.log(replaceAllAs(initialInput, 0));
will output
["KASSAB", "KASSaB", "KASSáB", "KaSSAB", "KaSSaB", "KaSSáB", "KáSSAB", "KáSSaB", "KáSSáB"]
How to find all occurrences of a character in a string. For example string is: "Hello world"
and user want to now the indexes of string where 'L' is present. Which is in example 2,3 and 9. How to find indexes like this in java-script/jquery ?
You can try something like the following code, from this answer:
function getIndicesOf(searchStr, str, caseSensitive) {
var startIndex = 0, searchStrLen = searchStr.length;
var index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
For example, if you wanted to find all b's and then write them to the document -
var foo = "foo bar baz bat";
var pos = foo.indexOf("b");
while(pos > -1) {
document.write(pos + "<br />");
pos = foo.indexOf("b", pos+1);
}
Output:
4
8
12
Here is some pseudocode. This is how you should try and work out the logic for problems before you try to start coding.
var indeces = {};
for(each character in string)
if(character == characterImLookingFor)
indeces.add(currentIndex);
return indeces;
function getIndexes(str,char) {
var index = str.indexOf(char);
var indexes = [];
while(index != -1) {
indexes.push(index);
index = str.indexOf(char,index+1);
}
return indexes;
}
Usage:
getIndexes("Hello world","l"); // returns [2,3,9]
You can also use regular expressions to achieve this:
var str = "Give me indexes of i in this string";
var regex = /i/gi, result;
while ((result = regex.exec(str)) ) {
console.log(result.index);
}
//Output: 1, 8, 19, 21, 26, 32
DEMO
I want something like this:
"abcdab".search(/a/g) //return [0,4]
Is it possible?
You can use the RegExp#exec method several times:
var regex = /a/g;
var str = "abcdab";
var result = [];
var match;
while (match = regex.exec(str))
result.push(match.index);
alert(result); // => [0, 4]
Helper function:
function getMatchIndices(regex, str) {
var result = [];
var match;
regex = new RegExp(regex);
while (match = regex.exec(str))
result.push(match.index);
return result;
}
alert(getMatchIndices(/a/g, "abcdab"));
You could use / abuse the replace function:
var result = [];
"abcdab".replace(/(a)/g, function (a, b, index) {
result.push(index);
});
result; // [0, 4]
The arguments to the function are as follows:
function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%
If you only want to find simple characters, or character sequences, you can use indexOf [MDN]:
var haystack = "abcdab",
needle = "a"
index = -1,
result = [];
while((index = haystack.indexOf(needle, index + 1)) > -1) {
result.push(index);
}
You can get all match indexes like this:
var str = "abcdab";
var re = /a/g;
var matches;
var indexes = [];
while (matches = re.exec(str)) {
indexes.push(matches.index);
}
// indexes here contains all the matching index values
Working demo here: http://jsfiddle.net/jfriend00/r6JTJ/
A non-regex variety:
var str = "abcdabcdabcd",
char = 'a',
curr = 0,
positions = [];
while (str.length > curr) {
if (str[curr] == char) {
positions.push(curr);
}
curr++;
}
console.log(positions);
http://jsfiddle.net/userdude/HUm8d/
Another non-regex solution:
function indexesOf(str, word) {
const split = str.split(word)
let pointer = 0
let indexes = []
for(let part of split) {
pointer += part.length
indexes.push(pointer)
pointer += word.length
}
indexes.pop()
return indexes
}
console.log(indexesOf('Testing JavaScript, JavaScript is the Best, JavaScript is Ultimate', 'JavaScript'))
Based on #jfriend00 answer but tidied up:
const getAllIndices = (str, strToFind) => {
const regex = RegExp(strToFind, 'g')
const indices = []
let matches
while (matches = regex.exec(str)) indices.push(matches.index)
return indices
}
console.log(getAllIndices('hello there help me', 'hel'))
console.log(getAllIndices('hello there help me', 'help'))
console.log(getAllIndices('hello there help me', 'xxxx'))