Problem
I know how to find out if a string contains a substring like this where you are looking for one word:
var s = "define foo";
alert(s.indexOf("define") > -1);
But how could I check for multiple different words/substrings using an array?
Example not working code that makes sense in my mind but doesn't work:
query = "Define what is grape juice and how to drink it?"
var terms = ["define", "what is", "how to"];
alert(query.indexOf(terms) > -1);
Thanks~!
Try this out:
var phrase = 'texttexttexttexttexttexttext';
var terms = ['word1', 'word2', 'word3'];
function check(string) {
var match = false;
for(var i=0;i<terms.length && !match;i++) {
if(string.indexOf(terms[i]) > -1) {
match = true;
}
}
return match;
}
//example
if(check(phrase)) {
//iftrue
} else {
//iffalse
}
You can use $.each() in jQuery to iterate through the terms array, and check each of them individually against the string. In the code below, I create a new JSON object called matchedTerms that will log the term and its index in the string. See demo here: http://jsfiddle.net/teddyrised/ktuuoprp/1/
var query = "Define what is grape juice and how to drink it?",
terms = ["define", "what is", "how to"],
matchedTerms = [];
$.each(terms, function(i,v) {
var match = query.indexOf(v);
matchedTerms.push({
'term': v,
'index': match
});
});
Even better: you can build a conditional statement in there so that the matchedTerms will only produce a simple array. See demo here: http://jsfiddle.net/teddyrised/ktuuoprp/2/
var query = "Define what is grape juice and how to drink it?",
terms = ["define", "what is", "how to"],
matchedTerms = [];
$.each(terms, function(i,v) {
var match = query.indexOf(v);
if(match > -1) matchedTerms.push(v);
});
console.log(matchedTerms);
p/s: If you want to perform case-insensitive matches, it helps to convert the query into lowercase, i.e. newQuery = query.toLowerCase(query);
You want to see if an array includes a string. There are a few ways to do it. This is answered well here.
Here are 2 options, copied from there:
Option 1:
$.indexOf is effectively a wrapper for Array.prototype.indexOf in browsers that support it (almost all of them these days), while providing a shim in those that don't. It is essentially equivalent to adding a shim to Array.prototype, which is a more idiomatic/JSish way of doing things. MDN provides such code. These days I would take this option, rather than using the jQuery wrapper.
Option 2:
jQuery offers $.inArray:
var found = $.inArray('specialword', categories) > -1;
Note that inArray returns the index of the element found, so 0 indicates the element is the first in the array. -1 indicates the element was not found.
Example.
Related
How change strings in javascript arrays. I want to change array codes to strings.
How change strings in javascript arrays. I want to change array codes to strings.
How to get this;
var _0x1576 = ["SayHello", "GetCount", "Message : ", "You are welcome."];
function NewObject(_0x7aa7x2) {
var _0x7aa7x3 = 0;
this.SayHello = function (_0x7aa7x4) {
_0x7aa7x3++;
alert(_0x7aa7x2 + _0x7aa7x4);
};
this.GetCount = function () {
return _0x7aa7x3
};
}
var obj = new NewObject("Message : ");
obj.SayHello("You are welcome.");
from;
var _0x1576 = ["SayHello", "GetCount", "Message : ", "You are welcome."];
function NewObject(_0x7aa7x2) {
var _0x7aa7x3 = 0;
this[_0x1576[0]] = function (_0x7aa7x4) {
_0x7aa7x3++;
alert(_0x7aa7x2 + _0x7aa7x4);
};
this[_0x1576[1]] = function () {
return _0x7aa7x3
};
}
var obj = new NewObject(_0x1576[2]);
obj.SayHello(_0x1576[3]);
EDIT: So you have some code, where all the variable names have been replaced by numbers or indices into this global array of names, and you would like to be able to read it. There is already an answer to this question, which contains links to a bunch of useful deobfuscation tools.
Your case here looks fairly trivial - it appears that you could just do a string search and replace, substituting in the array value every time it is indexed. The regexp /_0x1576\[(\d+)\]/g should find everything that accesses the variable _0x1576 with an integer index. The inner group (\d+) should give you the index with which it was found. You could use something like this to do deobfuscate your source. However, some of the names have been lost in the obfuscation process; i.e. the name of the parameter 0x7aa7x4 in the SayHello function can't be restored. You will have to read the method, understand what its' purpose is, and try to come up with a meaningful name yourself.
One question though - just how much code do you have like this? If there are only a few names in the array of strings, then #Nina Scholz's suggestion seems fairly reasonable. Just go through them one by one, in a text editor, and use the 'Find and Replace' functionality.
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
For example, i have an array like this:
var arr = [
{"keyword": "Sample 1", "item": {"title":"Sample Title", "url": "/sample"}},
{"keyword": "Foo 1", "item": {"title":"Foo Title", "url": "/sample"}}
];
I want to search in the "keyword" key, like when a user presses a key from their input and return that matches objects.
If user presses to "s" key, then first [0], element must return. Like using the SQL LIKE statement.
$("#query").on('keypress', function () {
var result = $.grep(keywords, function(e){
//I do not know what should i do here.
});
});
If you want to use $.grep you can do it like this:
$("#query").on('keyup', function() {
var search = this.value.toLowerCase();
var result = $.grep(keywords, function(el) {
return el.keyword.toLowerCase().indexOf(search) > -1;
});
});
Demo: http://jsfiddle.net/9TPSa/
Also note, that I switched to keyup event to be able to read updated this.value.
Use the Array.prototype.filter method:
Array.prototype.filterBy = function(attr, value) {
return this.filter(function(elem){
return elem[attr].indexOf(value) !== -1;
});
}
Then arr.filterBy('keyword', '1') would return both the objects(in your arr array), while arr.filterBy('keyword', 'oo') would return only the second one.
DEMO
The answer is simple: YOu have to loop through all of your objects, look at each keyword entry and decide wether it matches your search or not. SOmething like this:
var results = [];
for (var i = 0 ; i < arr.length ; i++) {
if (arr[i].keyword == "what ever you are looking for") {
results.push(arr[i]);
}
}
If you only need the frist match (and not all of them), you can simplify it:
var result;
for (var i = 0 ; i < arr.length ; i++) {
if (arr[i].keyword == "what ever you are looking for") {
result = arr[i];
break;
}
}
If you're not looking for equality, but need to use placeholders, take al look at String.prototype.indexOf() or regular expressions.
If you want to use $.grep() at all costs (there isn't too much difference to looping manually though, it does loop as well, just itnernally), you can - it'd look like this:
$("#query").on('keypress', function () {
var result = $.grep(keywords, function(e){
return (e.keyword == "whatever you are looking for again");
// use regular expressions or .indexOf again if you don't want to test equallity
});
});
Looping over large strucutres however (as you're comparing to databases, I suspect you have A LOT of those objects inside arr?) is very inefficient however. The fact that you HAVE TO loop indicates bad design. If you really got a lot of them, you might consider using a data structure that supports indexing, like a Hash Table/Map (those are not implemented in the core Java API; but are easy to implement on yoru own). They won't work if you need placeholders though, they're only an advantage when using equality to match results.
You could try using jQuery UI's AutoComplete... http://jqueryui.com/autocomplete/
You'll have to reduce your array to just the fields you're wanting to be searchable (ie. string literals for the keyword property, like ["Sample 1", "Foo 1"]) and pass that as the source in the autocomplete options.
Then hook into the change event http://api.jqueryui.com/autocomplete/#event-change and pull out the rest of your object from the original array.
EDIT : If you want to use grep, here is an example that gets the results using that method, but how you display them as auto options is then the next step!
http://jsfiddle.net/eQp3h/
var arr = [
{"keyword": "Sample 1", "item": {"title":"Sample Title", "url": "/sample"}},
{"keyword": "Foo 1", "item": {"title":"Foo Title", "url": "/sample"}}
];
$("#query").on('keyup', function () {
var regExp = new RegExp("^" + $(this).val(), "i");
var result = $.grep(arr, function(e, i){
var match = regExp.test(e.keyword);
return match;
});
$("#results").text(JSON.stringify(result));
});
Try this
$("body").on("keyup","#query",function(e){
var str = $("#query").val().toLowerCase();
var newarr = $.grep(arr,function(n,i){
return n.keyword.toLowerCase().search(str)!=-1;
});
});
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);
I have an array of items (terms), which will be put as <option> tags in a <select>. If any of these items are in another array (termsAlreadyTaking), they should be removed first. Here is how I have done it:
// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add.
for (var i = 0; i < terms.length; i++)
{
for (var iAlreadyTaking = 0; iAlreadyTaking < termsAlreadyTaking.length; iAlreadyTaking++)
{
if (terms[i]['pk'] == termsAlreadyTaking[iAlreadyTaking]['pk'])
{
terms.splice(i, 1); // remove terms[i] without leaving a hole in the array
continue;
}
}
}
Is there a better way to do this? It feels a bit clumsy.
I'm using jQuery, if it makes a difference.
UPDATE Based on #Matthew Flaschen's answer:
// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add.
var options_for_selector = $.grep(all_possible_choices, function(elem)
{
var already_chosen = false;
$.each(response_chosen_items, function(index, chosen_elem)
{
if (chosen_elem['pk'] == elem['pk'])
{
already_chosen = true;
return;
}
});
return ! already_chosen;
});
The reason it gets a bit more verbose in the middle is that $.inArray() is returning false, because the duplicates I'm looking for don't strictly equal one another in the == sense. However, all their values are the same. Can I make this more concise?
var terms = $.grep(terms, function(el)
{
return $.inArray(el, termsAlreadyTaking) == -1;
});
This still has m * n performance (m and n are the lengths of the arrays), but it shouldn't be a big deal as long as they're relatively small. To get m + n, you could use a hashtable
Note that ECMAScript provides the similar Array.filter and Array.indexOf. However, they're not implemented in all browsers yet, so you would have to use the MDC implementations as a fallback. Since you're using jQuery, grep and inArray (which uses native indexOf when available) are easier.
EDIT:
You could do:
var response_chosen_pk = $.map(response_chosen_items, function(elem)
{
return elem.pk;
});
var options_for_selector = $.grep(all_possible_choices, function(elem)
{
return $.inArray(elem.pk, response_chosen_pk) == -1;
});
http://github.com/danstocker/jorder
Create a jOrder table on termsAlreadyTaking, and index it with pk.
var table = jOrder(termsAlreadyTaking)
.index('pk', ['pk']);
Then you can search a lot faster:
...
if ([] == table.where([{ pk: terms[i].pk }]))
{
...
}
...