I want to finn the indexOF first non-aplhabetic char from a certain postion on
Example
abc4sss5gggg10
I wan to to get the position of 5 but to specify where I start searching
Use a combination of regular expressions and the substring function:
var str = "abc4sss5gggg10";
var indexToSearchFrom = 6;
var index = str.substring(indexToSearchFrom).search(/[^A-Za-z]/);
To get the index of first non-alpha char after the 4th position.
> 'abc4sss5gggg10'.replace(/^.{4}/, "").match(/[^a-z]/i)
[ '5',
index: 3,
input: 'sss5gggg10' ]
> 'abc4sss5gggg10'.replace(/^.{4}/, "").match(/[^a-z]/i)['index']
3
I think this is what you need:
I modified Mathijs Segers's code so it looks like this:
function StartSearching(str, startFrom) {
for (var i = startFrom; i<str.length;i++) {
if (!isNaN(str[i])) {
return i;
}
}
}
Consider first this post here Return positions of a regex match() in Javascript?
Then know that to find the first numeric value you have to use
var n = 2; // my starting position
var match = /[0-9]/.exec("abc4sss5gggg10".substring(n));
if (match) {
alert("match found at " + match.index);
}
Use substring to remove the first n characters
Your first thought might be regex, allthough those are heavy I'd probably go something like
getFirstNonAlpha(str) {
for (var i = 0; i<str.length;i++) {
if (!isNaN(str[i]) {
return i;
}
}
return false;
}
isNaN means isnotanumber so if it matches a number it'll return false and you can return the index.
Check which you need and which has a better speed if this is even an issue. Also this function won't help you with !##$%^&*()_ etc.
var str = "abc4sss5gggg10";
function searchIndex(index, strng) {
var arr = strng.split("");
for (var i = index; i < arr.length; i++) {
if (!isNaN(arr[i])) {
return i;
}
}
return -1;
}
alert(searchIndex(4, str));
DEMO
Related
good morning, sorry first of all for my english. I'm trying to do a double loop to iterate through two strings, the thing is, I want the ocrString to start one position later each time, so that it can iterate through the string in order to see if there are any matches. That is, I want to find the matches without necessarily being equal in length and without being able to order it.
let ocrString = "casaidespcasa";
let pattern = "idesp";
let conteo = 0;
checkIDESP(ocrString, pattern);
function checkIDESP(ocrString, pattern) {
let ocrStringSeparado = ocrString.split("");
let patternSeparado = pattern.split("");
for (i = 0; i < ocrStringSeparado.length; i++) {
for (x = 0; x < patternSeparado.length; x++) {
console.log(ocrStringSeparado[i], pattern[x]);
if (ocrStringSeparado[i] == pattern[x]) {
conteo++;
}
}
}
if (conteo <= 3) {
console.log(conteo, "No sé si es un dni");
} else {
console.log(conteo, "es un dni");
}
}
Some way to go through the position of an array so that it first starts with 'Casaidespcasa' and then 'Asaidespcasa' etc.
That won't answer totally to your question (I don't really understand by the way).
Now for the last part:
"Some way to go through the position of an array so that it first starts with 'Casaidespcasa' and then 'Asaidespcasa' etc."
Perhaps that can help for you to solve your problem.
let ocrString = "casaidespcasa";
let ocrStringSeparado = ocrString.split("");
decreaseArr(ocrStringSeparado);
decreaseStr(ocrString);
function decreaseArr(arr) {
console.log(arr);
arr.shift();
// do something...
if (arr.length > 0) {
decreaseArr(arr);
}
}
function decreaseStr(str) {
console.log(str);
str = str.substring(1);
// do something...
if (str.length > 0) {
decreaseStr(str);
}
}
First function is with array, second with string.
Well, maybe the following would work for you?
const string = "casaidespcasa";
function comp(str, pat){
let pl=pat.length, sl=str.length, res=[];
for (let i=0; i<=sl-pl; i++){
let s=str.slice(i,i+pl); // get a portion of the original string
let n=s.split("").reduce((a,c,j)=>a+(c==pat[j] ? 1 : 0), 0); // count matches
if (n>2) res.push([i,s]); // at least 3 character must match!
}
return res;
}
// do the string comparison with an array of patterns:
["idesp","1detp","deaspdc","cosa","asaic"].forEach(p=>console.log(p+":",comp(string,p)))
The function returns an array of possible "fuzzy" matches: Each entry is an array, containing the position and the matching substring.
I'm looking for letters (a to m) in the string using regex. I already found a way to do the same thing without regex, but is it possible to do this with regex and is it a good or bad idea to use regex when counting specific letters in the string?
When using regex findError.length value is wrong for me, the other way is working fine
This is how I search for letters using regex
function printerError(s) {
let findError = s.match(/[a-mA-M]+/g).toString();
let sum = (s.length - findError.length);
return sum + '/' + s.length;
}
console.log(printerError("anananaanaann"));
**
Working code
function printerError2(s) {
const goodLetters = Array.from("abcdefghijklm");
let total = s.length;
let badLetters = 0;
for (let i = 0; i < total; i++) {
if ( !goodLetters.includes(s.charAt(i)) ) {
badLetters++;
}
}
return `${badLetters}/${total}`;
}
console.log(printerError2("anananaanaann"));
This returns you the number of chars between a-mA-M in your string:
function printerError(s) {
return s.length - s.replace(/[a-mA-M]/g, '').length;
}
console.log(printerError("anananaanaann"));
Or you can even do:
function printerError(s) {
return (s.match(/[a-mA-M]/g) || []).length;
}
console.log(printerError("anananaanaann"));
I try to match/get all repetitions in a string. This is what I've done so far:
var str = 'abcabc123123';
var REPEATED_CHARS_REGEX = /(.).*\1/gi;
console.log( str.match(REPEATED_CHARS_REGEX) ); // => ['abca', '1231']
As you can see the matching result is ['abca', '1231'], but I excpect to get ['abc', '123']. Any ideas to accomplish that?
2nd question:
Another thing I excpect, is to make it possible to change the duration how often a char needs to be in the string to get matched...
For example if the string is abcabcabc and the repetation-time is set to 2 it should result in ['abcabc']. If set to 3 it should be ['abc'].
Update
A non-RegExp solution is perfectly alright!
Well, I think falsetru had a good idea with a zero-width look-ahead.
'abcabc123123'.match(/(.+)(?=\1)/g)
// ["abc", "123"]
This allows it to match just the initial substring while ensuring at least 1 repetition follows.
For M42's follow-up example, it could be modified with a .*? to allow for gaps between repetitions.
'abc123ab12'.match(/(.+)(?=.*?\1)/g)
// ["ab", "12"]
Then, to find where the repetition starts with multiple uses together, a quantifier ({n}) can be added for the capture group:
'abcabc1234abc'.match(/(.+){2}(?=.*?\1)/g)
// ["abcabc"]
Or, to match just the initial with a number of repetitions following, add the quantifier within the look-ahead.
'abc123ab12ab'.match(/(.+)(?=(.*?\1){2})/g)
// ["ab"]
It can also match a minimum number of repetitions with a range quantifier without a max -- {2,}
'abcd1234ab12cd34bcd234'.match(/(.+)(?=(.*?\1){2,})/g)
// ["b", "cd", "2", "34"]
This solution may be used if you don't want to use regex:
function test() {
var stringToTest = 'find the first duplicate character in the string';
var a = stringToTest.split('');
for (var i=0; i<a.length; i++) {
var letterToCompare = a[i];
for (var j=i+1; j<a.length; j++) {
if (letterToCompare == a[j]) {
console.log('first Duplicate found');
console.log(letterToCompare);
return false;
}
}
}
}
test()
The answer above returns more duplicates than there actually are. The second for loop causes the problem and is unnecessary. Try this:
function stringParse(string){
var arr = string.split("");
for(var i = 0; i<arr.length; i++){
var letterToCompare = arr[i];
var j= i+1;
if(letterToCompare === arr[j]){
console.log('duplicate found');
console.log(letterToCompare);
}
}
}
var duplicateCheck = function(stru) {
var flag = false;
for (let o = 0; o < stru.length; o++) {
for (let p = 0; p < stru.length; p++) {
if (stru.charAt(o) === stru.charAt(p) && o!==p) {
flag = true;
break;
}
}
}
return flag;
}
true ==> duplicate found
Say you have the following string:
FJKAUNOJDCUTCRHBYDLXKEODVBWTYPTSHASQQFCPRMLDXIJMYPVOHBDUGSMBLMVUMMZYHULSUIZIMZTICQORLNTOVKVAMQTKHVRIFMNTSLYGHEHFAHWWATLYAPEXTHEPKJUGDVWUDDPRQLUZMSZOJPSIKAIHLTONYXAULECXXKWFQOIKELWOHRVRUCXIAASKHMWTMAJEWGEESLWRTQKVHRRCDYXNT
LDSUPXMQTQDFAQAPYBGXPOLOCLFQNGNKPKOBHZWHRXAWAWJKMTJSLDLNHMUGVVOPSAMRUJEYUOBPFNEHPZZCLPNZKWMTCXERPZRFKSXVEZTYCXFRHRGEITWHRRYPWSVAYBUHCERJXDCYAVICPTNBGIODLYLMEYLISEYNXNMCDPJJRCTLYNFMJZQNCLAGHUDVLYIGASGXSZYPZKLAWQUDVNTWGFFY
FFSMQWUNUPZRJMTHACFELGHDZEJWFDWVPYOZEVEJKQWHQAHOCIYWGVLPSHFESCGEUCJGYLGDWPIWIDWZZXRUFXERABQJOXZALQOCSAYBRHXQQGUDADYSORTYZQPWGMBLNAQOFODSNXSZFURUNPMZGHTAJUJROIGMRKIZHSFUSKIZJJTLGOEEPBMIXISDHOAIFNFEKKSLEXSJLSGLCYYFEQBKIZZTQQ
XBQZAPXAAIFQEIXELQEZGFEPCKFPGXULLAHXTSRXDEMKFKABUTAABSLNQBNMXNEPODPGAORYJXCHCGKECLJVRBPRLHORREEIZOBSHDSCETTTNFTSMQPQIJBLKNZDMXOTRBNMTKHHCZQQMSLOAXJQKRHDGZVGITHYGVDXRTVBJEAHYBYRYKJAVXPOKHFFMEPHAGFOOPFNKQAUGYLVPWUJUPCUGGIXGR
AMELUTEPYILBIUOCKKUUBJROQFTXMZRLXBAMHSDTEKRRIKZUFNLGTQAEUINMBPYTWXULQNIIRXHHGQDPENXAJNWXULFBNKBRINUMTRBFWBYVNKNKDFR
I'm trying to find the smallest substring containing the letters ABCDA.
I tried a regex approach.
console.log(str.match(/[A].*?[B].*?[C].*?[D].*?[A]/gm).sort((a, b) => a.length - b.length)[0]);
This works, but it only find strings where ABCDA appear (in that order). Meaning it won't find substring where the letters appear in a order like this: BCDAA
I'm trying to change my regex to account for this. How would I do that without using | and type out all the different cases?
You can't.
Let's consider a special case: Assume the letters you are looking for are A, A, and B. At some point in your regexp there will certainly be a B. However, the parts to the left and to the right of the B are independent of each other, so you cannot refer from one to the other. How many As are matched in the subexpression to the right of the B depends on the number of As being already matched in the left part. This is not possible with regular expressions, so you will have to unfold all the different orders, which can be many!
Another popular example that illustrates the problem is to match opening brackets with closing brackets. It's not possible to write a regular expression asserting that in a given string a sequence of opening brackets is followed by a sequence of closing brackets of the same length. The reason for this is that to count the brackets you would need a stack machine in contrast to a finite state machine but regular expressions are limited to patterns that can be matched using FSMs.
This algorithm doesn't use a regex, but found both solutions as well.
var haystack = 'FJKAUNOJDCUTCRHBYDLXKEODVBWTYPTSHASQQFCPRMLDXIJMYPVOHBDUGSMBLMVUMMZYHULSUIZIMZTICQORLNTOVKVAMQTKHVRIFMNTSLYGHEHFAHWWATLYAPEXTHEPKJUGDVWUDDPRQLUZMSZOJPSIKAIHLTONYXAULECXXKWFQOIKELWOHRVRUCXIAASKHMWTMAJEWGEESLWRTQKVHRRCDYXNTLDSUPXMQTQDFAQAPYBGXPOLOCLFQNGNKPKOBHZWHRXAWAWJKMTJSLDLNHMUGVVOPSAMRUJEYUOBPFNEHPZZCLPNZKWMTCXERPZRFKSXVEZTYCXFRHRGEITWHRRYPWSVAYBUHCERJXDCYAVICPTNBGIODLYLMEYLISEYNXNMCDPJJRCTLYNFMJZQNCLAGHUDVLYIGASGXSZYPZKLAWQUDVNTWGFFYFFSMQWUNUPZRJMTHACFELGHDZEJWFDWVPYOZEVEJKQWHQAHOCIYWGVLPSHFESCGEUCJGYLGDWPIWIDWZZXRUFXERABQJOXZALQOCSAYBRHXQQGUDADYSORTYZQPWGMBLNAQOFODSNXSZFURUNPMZGHTAJUJROIGMRKIZHSFUSKIZJJTLGOEEPBMIXISDHOAIFNFEKKSLEXSJLSGLCYYFEQBKIZZTQQXBQZAPXAAIFQEIXELQEZGFEPCKFPGXULLAHXTSRXDEMKFKABUTAABSLNQBNMXNEPODPGAORYJXCHCGKECLJVRBPRLHORREEIZOBSHDSCETTTNFTSMQPQIJBLKNZDMXOTRBNMTKHHCZQQMSLOAXJQKRHDGZVGITHYGVDXRTVBJEAHYBYRYKJAVXPOKHFFMEPHAGFOOPFNKQAUGYLVPWUJUPCUGGIXGRAMELUTEPYILBIUOCKKUUBJROQFTXMZRLXBAMHSDTEKRRIKZUFNLGTQAEUINMBPYTWXULQNIIRXHHGQDPENXAJNWXULFBNKBRINUMTRBFWBYVNKNKDFR';
var needle = 'ABCDA'; // the order of letters doesn't matter
var letters = {};
needle.split('').forEach(function(ch) {
letters[ch] = letters[ch] || 0;
letters[ch]++;
});
var shortestSubstringLength = haystack.length;
var shortestSubstrings = []; // storage for found substrings
var startingPos = 0;
var length;
var currentPos;
var notFound;
var letterKeys = Object.keys(letters); // unique leters
do {
lettersLeft = JSON.parse(JSON.stringify(letters)); // copy letters count object
notFound = false;
posStart = haystack.length;
posEnd = 0;
letterKeys.forEach(function(ch) {
currentPos = startingPos;
while (!notFound && lettersLeft[ch] > 0) {
currentPos = haystack.indexOf(ch, currentPos);
if (currentPos >= 0) {
lettersLeft[ch]--;
posStart = Math.min(currentPos, posStart);
posEnd = Math.max(currentPos, posEnd);
currentPos++;
} else {
notFound = true;
}
}
});
if (!notFound) {
length = posEnd - posStart + 1;
startingPos = posStart + 1; // starting position for next iteration
}
if (!notFound && length === shortestSubstringLength) {
shortestSubstrings.push(haystack.substr(posStart, length));
}
if (!notFound && length < shortestSubstringLength) {
shortestSubstrings = [haystack.substr(posStart, length)];
shortestSubstringLength = length;
}
} while (!notFound);
console.log(shortestSubstrings);
Maybe not as clear as using regex could be (well, for me regex are never really clear :D ) you can use brute force (not so brute)
Create an index of "valid" points of your string (those with the letters you want) and iterate with a double loop over it getting substrings containing at least 5 of those points, checking that they are valid solutions. Maybe not the most efficient way, but easy to implement, to understand, and probably to optimize.
var haystack="UGDVWUDDPRQLUZMSZOJPSIKAIHLTONYXAULECXXKWFQOIKELWOHRVRUCXIAASKHMWTMAJEWGEESLWRTQKVHRRCDYXNTLDSUPXMQTQDFAQAPYBGXPOLOCLFQNGNKPKOBHZWHRXAWAWJKMTJSLDLNHMUGVVOPSAMRUJEYUOBPFNEHPZZCLPNZKWMTCXERPZRFKSXVEZTYCXFRHRGEITWHRRYPWSVAYBUHCERJXDCYAVICPTNBGIODLYLMEYLISEYNXNMCDPJJRCTLYNFMJZQNCLAGHUDVLYIGASGXSZYPZKLAWQUDVNTWGFFYFFSMQWUNUPZRJMTHACFELGHDZEJWFDWVPYOZEVEJKQWHQAHOCIYWGVLPSHFESCGEUCJGYLGDWPIWIDWZZXRUFXERABQJOXZALQOCSAYBRHXQQGUDADYSORTYZQPWGMBLNAQOFODSNXSZFURUNPMZGHTAJUJROIGMRKIZHSFUSKIZJJTLGOEEPBMIXISDHOAIFNFEKKSLEXSJLSGLCYYFEQBKIZZTQQXBQZAPXAAIFQEIXELQEZGFEPCKFPGXULLAHXTSRXDEMKFKABUTAABSLNQBNMXNEPODPGAORYJXCHCGKECLJVRBPRLHORREEIZOBSHDSCETTTNFTSMQPQIJBLKNZDMXOTRBNMTKHHCZQQMSLOAXJQKRHDGZVGITHYGVDXRTVBJEAHYBYRYKJAVXPOKHFFMEPHAGFOOPFNKQAUGYLVPWUJUPCUGGIXGR";
var needle="ABCD";
var size=haystack.length;
var candidate_substring="";
var minimal_length=size;
var solutions=new Array();
var points=Array();
for(var i=0;i<size;i++){
if(needle.indexOf(haystack[i])>-1) points.push(i);
}
var limit_i= points.length-4;
var limit_k= points.length;
for (var i=0;i<limit_i;i++){
for(var k=i;k<limit_k;k++){
if(points[k]-points[i]+1<=minimal_length){
candidate_substring=haystack.substr(points[i],points[k]-points[i]+1);
if(is_valid(candidate_substring)){
solutions.push(candidate_substring);
if(candidate_substring.length < minimal_length) minimal_length=candidate_substring.length;
}
}
}
}
document.write('<p>Solution length:'+minimal_length+'<p>');
for(var i=0;i<solutions.length;i++){
if(solutions[i].length<=minimal_length) document.write('<p>Solution:'+solutions[i]+'<p>');
}
function is_valid(candidate_substring){
//verify we've got all characters
for(var j=0;j<candidate_substring.length;j++){
if(candidate_substring.indexOf(needle.charAt(j))<0) return false;
}
//...and verify we have two "A"
if(candidate_substring.indexOf("A")==candidate_substring.lastIndexOf("A")) return false;
return true;
}
Just had this problem in an interview as a coding assignment and came up with another solution, (it's not as optimal as the one above but maybe it's easier to understand).
function MinWindowSubstring(strArr) {
const N = strArr[0];
const K = strArr[1];
const letters = {};
K.split('').forEach( (character) => {
letters[character] = letters[character] ? letters[character] + 1 : 1;
});
let possibleSequencesList = [];
const letterKeys = Object.keys(letters);
for(let i=0; i< N.length; i++) {
const char = N[i];
if (new String(letterKeys).indexOf(char) !== -1) {
// found a character in the string
// update all previus sequences
possibleSequencesList.forEach((seq) => {
if(!seq.sequenceComplete) {
seq[char] = seq[char]-1;
seq.lastIndex = i;
// check if sequence is complete
var sequenceComplete = true;
letterKeys.forEach( (letter) => {
if(seq[letter] > 0) {
sequenceComplete = false;
}
});
seq.sequenceComplete = sequenceComplete
}
})
// create a new sequence starting from it
const newSeq = {
startPoint: i,
lastIndex: i,
sequenceComplete: false,
...letters
}
newSeq[char] = newSeq[char]-1;
possibleSequencesList.push(newSeq);
}
}
// cleanup sequences
let sequencesList = possibleSequencesList.filter(sequence => sequence.sequenceComplete);
let output = [];
let minLength = N.length;
// find the smalles one
sequencesList.forEach( seq => {
if( (seq.lastIndex - seq.startPoint) < minLength) {
minLength = seq.lastIndex - seq.startPoint;
output = N.substring(seq.startPoint, seq.lastIndex + 1);
}
})
return output;
}
I have a javascript array like
var main_array = ["allen~1", "ajay~2", "raj~3"];
I have another array like
var sub_array=["allen", "ajay"];
EDIT
I need to check whether each values of sub_array is found in main_array, (i.e) whether 'allen' found in ["allen~1", "ajay~2", "raj~3"] so the values which do not match must be removed from the array. As the result "raj~3" must be removed from the main_array
How to achieve this?
I have tried indexOf(), match() but that fails since it expects an exact match like "allen~1"..
Thanks in advance
your question is kind if not so clear, but i think what you want to achieve is an array which contains all values from main_array which are part of sub_array? in your example the resulting array should be
["allen~1", "ajay~2"]
? if so see this:
then you need to loop over your sub-array, and check in your main_array:
var i, j, result = [];
for (i = 0; i < sub_array.length; i++) {
for (j = 0; j < main_array.length; j++) {
if (main_array[j].indexOf(sub_array[i]) != -1) {
result.push(main_array[j]);
}
}
}
see a working jsfiddle: http://jsfiddle.net/yf7Dw/
edit: Felix Kings answer is probably best, but if you dont want to use polyfills and must support older IE's you could use my solution
edit2: Array.splice is your friend if you want to remove the element from the main array. see the updated fiddle: http://jsfiddle.net/yf7Dw/2/
var i, j;
for (i = 0; i < sub_array.length; i++) {
for (j = 0; j < main_array.length; j++) {
if (main_array[j].indexOf(sub_array[i]) != -1) {
main_array.splice(j, 1);
}
}
}
You can use .every [MDN] and .some [MDN]:
var all_contained = sub_array.every(function(str) {
return main_array.some(function(v) {
return v.indexOf(str) > -1;
});
});
Have a look at the documentation for polyfills for older IE versions.
If you want to remove elements, you can use .filter [MDN] and a regular expression:
// creates /allen|ajay/
var pattern = new RegExp(sub_array.join('|'));
var filtered = main_array.filter(function(value) {
return pattern.test(value);
});
Values for which the test returns false are not included in the final array.
If the values in sub_array can contain special regular expression characters, you have to escape them first: Is there a RegExp.escape function in Javascript?.
Build a RegExp from the searched string and use match with it
string.match(new RegExp(searchedString + ".*"));
or
string.match(new RegExp(searchedString + "~[0-9]+"));
try
var globalBoolean =true;
$.each(subarray, function (index,value) {
if ( !($.inArray(value, main_array) > -1)){
globalBoolean =false;
}
});
If globalBoolean is true then equal.
try
var main_array = ["allen~1", "ajay~2", "raj~3"];
var main_array1 = new Array();
for (var i = 0; i < main_array.length; i++) {
main_array1.push(main_array[i].split('~')[0])
}
var sub_array = ["allen", "ajay"];
if ($.inArray('allen', main_array1) == -1) {
alert('false');
}
else {
alert('true');
}
Just another solution...
var filtered_array = jQuery.grep(main_array, function(n1, i1){
var y = jQuery.grep(sub_array, function(n2, i2){
return n1.indexOf(n2) !== -1; // substring found?
});
return y.length; // 0 == false
});
Get underscore js. Then do this:
var myarray = ["Iam","Iamme","meIam"];
var sub_ar = ["am", "amI", "amme"];
_.each(myarray, function(x){
_.each(sub_ar, function(y){
if(x == y)
{
console.log(y + " is a match");
});
});
Sorry. This wont work because you are looking for substring. My bad. Try this:
var myarray = ["Iam","Iamme","meIam"];
var sub_ar = ["am", "amI", "amme"];
_.each(myarray, function(x){
_.each(sub_ar, function(y){
if(x.indexOf(y) !== -1)
{
console.log("match found");
});
});