I’d like to capture whether a value is contained in a string. I have a finite list of values to be matched against a comma separated variable length string that could be 400 characters long. Any occurrences of the string will only appear once, there won’t be any duplicates nor will there be two instances of a static list item in the string, e.g., the string will never contain both “Poor” and “Ultimate”.
Static List of Items
Poor Fair Good Better Best Ultimate
String to search against
Cake,Good,Pickles,System,Tires
I realize I can use indexOf and a bunch of IF statements, but I’m wondering if there’s a better of doing this, like assigning my static list to an array
var myList=new Array [“Poor”, “Fair”, “Good”, “Better”, “Best”, “Ultimate”];
I don’t know how to loop through the array and the string to return the value found, e.g., “Good” in this example. What is the best way of doing this – best defined as most efficient, fastest and easiest to maintain (assuming those aren’t contradictions)?
Thanks
Yes, you're in the right way, in my opinion. Look:
var myList= ["Poor", "Fair", "Good", "Better", "Best", "Ultimate"];
var stringList = "Cake,Good,Pickles,System,Tires";
for (var i = 0; i < myList.length; i++)
{
if (stringList.indexOf(myList[i]) > -1)
{
window.alert("Contains: " + myList[i]);
break;
}
}
Demo.
If you're secure that those values will match and you don't need any validation of that string in the list, that simple loop - in vanilla js - will work. Fast, efficient and easy to maintain.
Depending of your needs, you can use the array functions forEach or every :
var myList=['Poor', 'Fair', 'Good', 'Better', 'Best', 'Ultimate'];
var myString = "Cake,Good,Pickles,System,Tires";
var valContainedInString = [];
myList.forEach(isInString);
function isInString(pVal, pIndex, pArray) {
if(myString.indexOf(pVal) >= 0) {
valContainedInString.push(pVal);
}
}
for(var i = 0; i < valContainedInString.length; i++) {
console.println(valContainedInString[i]);
}
This will output : "good".
More info : foreach every
Related
Essentially, I have a Set of words, about 250,000 of them and want to be able to return a list of which ones are found in a given string.
eg. input string is 'APPLEASEDITION', I want to return
[APP,APPLE,PLEA, PLEAS,PLEASE,PLEASED,lEA,LEAS,LEASE,LEASED,EA,EAS,EASE,EASED,AS,SEDITION,EDITION,IT,TI,ON]
I came up with this code, which works faster than the method mentioned above for shorter input strings (up to 15 characters), but doubles in execution time with each added letter:
const findWords = (instring, solutions = null) => {
if (!solutions) solutions = new Set();
if (!instring) {
return new Set();
}
if (words[instring]) {
solutions.add(instring);
}
const suffix = instring.slice(1);
const prefix = instring.slice(0, instring.length - 1);
if (!solutions.has(prefix))
solutions = new Set([...solutions, ...findWords(prefix, solutions)]);
if (!solutions.has(suffix))
solutions = new Set([...solutions, ...findWords(suffix, solutions)]);
return solutions;
};
Wondering if anyone can help me out optimizing the code?
Edit:
I made a different solution, it works much better
const getAllSubstrings = (str) => {
let result = [];
for (let i = 0; i < str.length; i++) {
for (let j = i + 1; j < str.length + 1; j++) {
result.push(str.slice(i, j));
}
}
return result;
}
const findWords = (instring) => {
const solutions = []
let subs = getAllSubstrings(instring)
for (let sub of subs) {
if (words[sub])
solutions.push(sub)
}
return solutions
}
Still open to possible improvements, but this works well enough for my use case
As it stands your logic assumes your input starts or ends with the phrase, but doesn't consider words in the middle - you'll need to generate permutations
Convert your dictionary to a hash where the words are keys - O(n) => O(1) - you can check if possible words are in the dictionary by checking dictionary[possibleWord]
You could convert your array of dictionary words into a binary search tree or a trie - there might be a performance benefit to converting your source text to a collection of BSTs/Tries, where each one represents a possible word/permutation, and then comparing BSTs/Tries rather than strings, but I'm not sure how that'd be faster than string comparison at the moment.
You can limit the length to the max length of a given permutation to the words in your dictionary. You'll end up with a lot of permutations, but possibly less than you have currently.
As the comments state you may want to do this server side for more power/in a language more efficient than JS, or using WASM.
Some javascript libraries that have binary search tree tools:
https://developers.google.com/closure/library/
https://www.npmjs.com/package/binary-search-tree
https://www.npmjs.com/package/trie-search
Alternatively, you might be able to create two hashes (one of permutations, one of dictionary words), or another data structure that's made for creating a "diff" or "overlap", and extract the keys that are in both sets.
I have search through quite a lot of questions here, but havent found one that i think fits my bill, so if you know of one please link to it.
I have an array that i want to search through for a specific number and if that number is in the array, i then want to take an action and if not then another action.
I have something like this
var Array = ["1","8","17","14","11","20","2","6"];
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8)
then change picture.src to srcpicture1
else
then change picture.src to srcpicture2
}
but this will run the lenght of the array and end up checking the last element of the array and since the last element is not 8 then it will change the picture to picture2.
Now i can see why this happens, i just dont have any ideas as to how to go about checking if an array contains a specific number.
Thanks in advance.
What you can do is write yourself a function to check if an element belongs to an array:
function inArray(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] == value) return true;
}
return false;
}
And the just do:
var arr = ["1","8","17","14","11","20","2","6"];
if (inArray(arr, 8)) {
// change picture.src to srcpicture1
} else {
// change picture.src to srcpicture2
}
It's a lot more readable to me.
For extra points you can add the function to the array prototype like so:
Array.prototype.has = function (value) {
for (var i = 0; i < this.length; i++) {
if (this[i] === value) return true;
}
return false;
};
And then the call would be
if (arr.has(8)) // ...
Pushing this even further, you can check for indexOf() method on array and use it - if not - replace it with the code above.
P.S. Try not to use Array for a variable name, since it's reserved for the actual array type.
use this
http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf
ie version
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf#Compatibility
Why don't just you abort the loop when you find the right number :
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8) {
//change picture.src to srcpicture1
break;
}
}
You could sort the array first then check the array only up to the point at which a number would be in the array, were it to exist.
If you have unique keys and a faster retrieval is what you care about a lot, you can consider using a map instead of an array (if there's a hard-bound case of using an array, then it won't work of course). If using a map, you just check "if( num in arr ) ".
My goal's create a filter search function, in particular actually I'm using .indexOf method that allow me to check if two string are equal. The problem's that if I've the compare string with space break like this: Hair Cut.
Example:
String to search: Hair
String contained in the object: Hair Cut
var cerca = $('#filter_service').val();
for(var i = 0; i < GlobalVariables.availableServices.length; i++) {
if (cerca.toLowerCase().contains(GlobalVariables.availableServices[i].name.toLowerCase()) != -1) {
console.log(GlobalVariables.availableServices[i].name)
}
}
How you can see I valorize the variable cerca that contains the string Hair in the example. I compare this with an object variable, how I said, the problem is if I insert the string Hair I get no response in console, also if I insert the string with break space like the compare string Hair Cut I get the console response.
How I can print a result also when the variable cerca is equal to the first character of the compair string? In particular Hai?
I don't know if I was clear, hope yes.
.contains() is for checking DOM element children. You said above that you are using .indexOf to check, but it doesn't look like you use it in your code?
var cerca = $('#filter_service').val();
var searchIn;
for(var i = 0; i < GlobalVariables.availableServices.length; i++) {
searchIn = GlobalVariables.availableServices[i].name.toLowerCase().split(' ');
for (j = 0; j < searchIn.length; j++) {
if (cerca.toLowerCase().split(' ').indexOf(searchIn[j].toLowerCase()) >= 0) {
console.log(GlobalVariables.availableServices[i].name);
}
}
}
$('#filter_service').on('input', function() {
var inputStr = $('#filter_service').val();
var similar = [];
for (i = 0; i < GlobalVariables.availableServices.length; i++) {
if (GlobalVariables.availableServices[i].name.toLowerCase().indexOf(inputStr.toLowerCase) >= 0) {
similar[similar.length] = GlobalVariables.availableServices[i].name;
}
}
// At this point, you can do whatever you want with the similar service
// names (all of the possible result names are included in the array, similar[].)
});
I can't test that code right now, but in theory, it should work.
Here is a JSFiddle demo:
http://jsfiddle.net/MrGarretto/vrp5pghr/
EDIT: Updated and fixed my errors
EDIT 2: Added the 'possible results' solution
EDIT 3: Added a JSFiddle
Didn't really found a solution to this for Javascript.
What I need; I want to insert an element into an array, but not really overwrite that element. Rather a 'dynamic' insert. Thus Insert element, then shift all elements underneath it by +1 index.
For instance:
I have an array "14S" "16S" "19S".
I know want to insert "15S".
The resulting array: "14S" "15S" "16S" "19S"
What i tried:
fullName = "15S"
low = 5;
cardsS[low] = fullName;
for (var i = low; i < cardsS.length; i++) {
cardsS[i + 1] = cardsS[i];
}
If you know the position you want to insert the element into:
Use the splice method. It's cheap and works exactly like you want. You can also insert multiple elements at once:
var strings = ["14S", "16S", "19S"];
strings.splice(1,0,"15S");
Result
"14S" "15S" "16S" "19S"
You should also use this solution if you don't want the array to be sorted in a specific way.
If you don't know the position you want to insert the element into:
You will have to resort to a push/sort combination, supplying your own sort algorithm (unless the standard sort is enough)
var strings = ["14S", "16S", "19S"];
strings.push("15S");
strings.sort(function(a, b){
if (a is less than b by some ordering criterion)
return -1;
if (a is greater than b by the ordering criterion)
return 1;
// a must be equal to b
return 0;
});
You can use Array.splice to insert a value:
var arr = ["14S","16S","19S"];
arr.splice(1,0,"15S");
// ^position after which to insert
// ^number of elements to delete (none here)
// ^value to insert ("15S" here)
// => arr is now ["14S","15S","16S","19S"]
If you don't know the position, you could use Array.indexOf to determine it:
var arr = ["14S","16S","19S"];
arr.splice((arr.indexOf('14S')>-1 && arr.indexOf(after)+1 || 0),0,"15S");
// ^use indexOf result if applicable or just insert
// (so, if no position, this turns into unshift ;)
You can create a method for it:
function arrayInsertAfter(array, after, value){
after = array.indexOf(after)>-1 && array.indexOf('14S')+1 || 0;
array.splice(after, 0, value);
return array;
}
// usage
var arr = arrayInsertAfter(["14S","16S","19S"],"14S","15S");
// => ["14S","15S","16S","19S"]
MDN link for Array.splice
you just need to use push() and then sort() functions :
var yourArray = ['14S', '16S', '19S'];
yourArray.push('15S');
yourArray.sort();
You want Array.splice.
This splices a new element at position 1.
arr.splice(1, 0, '155');
Fiddle
What you want is the splice function on the native array object.
var arr = [];
arr[0] = "14S";
arr[1] = "16S";
arr[2] = "19S";
arr.splice(2, 0, "15S");
console.log(arr.join());
The resulting array: 14S, 16S, 15S, 19S
If you do that, you will start at cardsS[5], which will have the value of "fullName".
The fact is that your cardsS as 4 values, so your array is 0 to 3. You can see that your array at position 4 is unbind.
Moreover, if you do cardsS[i + 1], you will be at position 6, which is unbind too.
What you have to do is to:
Check how many item you have in your array (Lenght, Count)
Create a new array with Lenght + 1
Check if your new item is > or < to your first item. If it is >, you have to add your first item, if not you have to add your new item
Do this until your array is full.
If you don't want to do like that, you can use Splice function, just check it, or use a sort function from javascript library.
Hope this can help you !
Try This:
fullName ="15S"
cardsS = ["14S", "16S", "19S"];
for (var k in cardsS)
{
if(parseInt(fullName) < parseInt(cardsS[k])){
cardsS.splice(k,0,fullName)
break;
}
}
:)
if you think is better:
fullName ="15S"
cardsS = ["14S", "16S", "19S"];
for (var k = 0; cardsS.length > k; k++)
{
if(parseInt(fullName) < parseInt(cardsS[k])){
cardsS.splice(k,0,fullName)
break;
}
}
In one of your comments you asked the difference between the splice method and the push+sort method.
Splice just cuts up your array and inserts/deletes values based on index.
Using above mentioned example:
var strings = ["14S", "16S", "19S"];
strings.splice(1,0,"15S");
This will literally place the "15S" on index 1. This is why there is a remark "If you don't know the position you want to insert the element into:"
In which case the push+sort method comes into play. At this point you don't have to go about counting your elements and making sure you place everything at the right location.
You literally just push your "15S" at the end of the array, and then have the sort() automatically sort everything for you.
This, granted that your array is indeed sortable. Some setups don't really allow you to sort your arrays (Like colors sorted by color in the rainbow ... you can't just sort them using sort()).
In this case KooiInc's response comes into play. At this point you know where your item needs to be. 15S comes after 14S, so you search for 14S, get that index, and use that index to splice.
At this point you still have to calculate yourself what element 15S will have to go after - in my rainbow example you'll have to actively remember where you want to 'insert' which color based on which colors are in your array at this moment.
In your example the values seem to be suited for normal sorting, so i would go with the Push+sort approach a few people mentioned.
var arr = [1,2,4,5,6];
var element = 3, pos=3;
for(i=arr.length-1; i>=pos-1; i--){
arr[i+1]=arr[i];
}
arr[pos-1]=element;
console.log(arr);
I am looping through an array of english phrases, and if i find a match, with the current text node, i replace it with it's translation in the non_english array. All of that works 100% for exact matches.
But for partial matches, I need to use the .match command, which allows for partial matches.
My code to search for exact matches is like this:
var found = $.inArray(value,en_lang);
Then if there is a found value, then do replacement of text. This method is fast and I love it.
However to do partial word/phrase matching, I have to use this looping code.
// loop thru language arrays
for (var x = en_count; x > 0; x--) {
// assign current from/to variables for replace
var from = en_lang[x];
var to = other_lang[x];
// if value match do translation
if (value.match(from)) {
content(node, value.replace(from, to));
}
// mark this node as translated
if ($.browser.msie == 'false') {
$(node).data('translated', 'yes');
}
}
This does the job but is pretty slow. After a lot of research, I have found that I can convert the english array to a list-based string via the join command.
But I am unable to come up with a function to search this list for a partial match, and return the position in the list.
I was trying out this old js function created in 2006. But I can't figure out how to get the position back, correctly.
function listfind(list, value, delimiters) {
if (!delimiters) {
var delimiters = ','
}
_TempListSplitArray = list.split(delimiters)
var FoundIdx = 0;
for (i = 0; i < _TempListSplitArray.length; i++) {
if (_TempListSplitArray[i] == value) {
FoundIdx = i + 1;
break
}
if (value.match(_TempListSplitArray[i])) {
FoundIdx = i + 1;
break
}
}
return FoundIdx
}
Thank you for your time.
Javascript has a foreach type of system but its still based on a loop
var array = ['hello', 'world'];
for(var key in array){
alert(array[key]);
}
Thats the best your getting for looping though an array but this way allso works with objects
var obj = {'one':'hello', 'two':'world'];
for(var key in obj){
alert("key: "+key+" value: "+obj[key]);
}
UPDATED for Comments on your question
You can just replace the text you know
var str = "hello World";
str = str.replace("hello", "Bye bye");
alert(str);