I'm trying to find the first character in an Array in JavaScript.
I have this a random function (not the best, but I am going to improve it):
function random() {
var Rand = Math.floor(Math.random()*myArray.length);
document.getElementById('tr').innerHTML = myArray[Rand];
}
And here's my Array list.
myArray = ["where", "to", "get", "under", "over", "why"];
If the user only wants arrays with W's, only words with a W in the first letter is shown. (Like "where" or "why")
I do not have a lot of experience with JavaScript from before and I have been sitting with this problem for ages.
There's indexOf() method of an array/string which can provide you with a position of a letter. First letter has a position of 0(zero), so
function filter(letter) {
var results = [];
var len = myArray.length;
for (var i = 0; i < len; i++) {
if (myArray[i].indexOf(letter) == 0) results.push(myArray[i]);
}
return results;
}
Here is a jsFiddle for it. Before running open the console(Chrome: ctrl+shift+i, or console in FireBug) to see resulting arrays.
You can filter the array to contain only specific values, such as the ones starting with 'w'
var words = ["where", "to", "get", "under", "over", "why"];
var wordsWithW = words.filter(function(word) {
return word[0] == 'w';
});
var randomWordWithW = wordsWithW[Math.floor(Math.random() * wordsWithW.length];
... // operate on the filtered array afterwards
If you plan to support the aged browsers you might want to consider using underscore.js or Prototype
When using underscore you could simply write this:
var randomWordWithW = _.chain(words).filter(function(word) {
return word[0] == 'w';
}).shuffle().first().value()
Related
I have a given word, that I want to match against a given list of words, mainList, and establish which words of that given list are anagrams of the given word, and add them to another list, subList.
I feel like my method to do this is fine, but it returns an unexpected result.
For example...
var word = 'master';
var mainList = ['stream', 'pidgeon', 'maters'];
var subList = [];
Then I take the word, split to an array of letters, alphabetise, and join back into a string. With this string I should be able match against any possible anagrams (which I will covert in the same way).
var mainSorted = [];
for (i = 0; i < word.length; i++) {
mainSorted = word.split('').sort().join();
}
This is where it goes wrong. I loop through the mainList array trying to establish if a given item, when converted, matches the original. If so, I want to push the word to the subList array.
for (var i = 0; i < mainList.length; i++) {
var subSorted = mainList[i].split('').sort().join;
if (mainSorted === subSorted) {
subList.push(mainList[i])
}
}
return subList;
...and the value I expect to see for subList is: ['stream', 'maters']
Yet I am returned an empty array instead.
I've gone through this so many times and I cannot see what's going wrong, would really appreciate some help!
Also, I'm aware there's probably more eloquent methods to do this (and I welcome any suggestions) but primarily I want to see where this is going wrong.
Thanks in advance.
You forgot () at the end of join
var subSorted = mainList[i].split('').sort().join;
should be
var subSorted = mainList[i].split('').sort().join();
One non-issue is
for (i = 0; i < word.length; i++) {
mainSorted = word.split('').sort().join();
}
doesnt need to be in a loop
mainSorted = word.split('').sort().join();
alone suffices
as a bonus, here's a tidier way of doing what you are doing
var word = 'master';
var mainList = ['stream', 'pidgeon', 'maters'];
var mainSorted = word.split('').sort().join();
return mainList.filter(function(sub) {
return sub.split('').sort().join() == mainSorted;
});
Having an array of arrays named data with following format:
> data[1].toString()
"Seed Keywords,disconnectors,EUR,210,0.03,,,,,N,Y,"
And another array named groupKeywordsText with a list of words to find inside the array data:
> console.log(groupKeywordsText);
["switch", "ac", "high", "switches", "disconnect", "voltage", "isolator"]
I need to create a set of new arrays that include only elements from data which contains a whole word from groupKeywordsText.
SOME EXAMPLES:
An array can be assigned in only one of the new arrays:
> data[3].toString()
"Keyword Ideas,ac,EUR,1900,0.00,1.58,,,,N,N,"
Will be assigned to the second new array, because "ac" is exactly one of the searched term.
An array can be assigned in multiple new arrays:
> data[12].toString()
"Keyword Ideas,high voltage,EUR,27100,0.00,1.58,,,,N,N,"
Will be assigned to the third new array, because "high side"
contains the term to search: "high".
Additionally, it will be included in the 5th array, as "voltage" also appears.
An array can be assigned in multiple new arrays, but not in others:
> data[18].toString()
"Keyword Ideas,isolator for switch,EUR,1100,0.00,1.58,,,,N,N,"
Will be assigned to the first new array, because "isolator for switch"
contains the term to search: "switch".
Additionally, it will be included in the 6th array, as "isolator" also appears.
However, it will not appear in the 4th array ("switches"), because we search for, and only exactly for, "switch".
An array cannot be assigned in new arrays:
> data[28].toString()
"Keyword Ideas,stackoverflow,EUR,1900,0.00,1.58,,,,N,N,"
Wont be assigned to a new array, because "stackoverflow" isn't a searched term.
So far, my code looks like:
for ( var i = 0, l = groupKeywordsText.length; i < l; i++ ) {
keywordToSearch = groupKeywordsText[i];
var length = data.length;
this["keywordGroup"+i] = [];
for(var j = 0; j < length; j++) {
if (data[j][1] == keywordToSearch) {
this["keywordGroup"+i].push(data[j][1]);
}
}
console.log(this["keywordGroup"+i]);
}
How can I search for whole (not partial) words inside a string?
To search for whole words inside a string, you can use:
var myString = 'longStringWithLotsOfWords';
var word = 'String';
var noWord = 'StackOverflow';
myString.indexOf(word) != -1; //true, 'String' is inside myString
myString.indexOf(noWord) != -1; //false, 'StackOverflow' is not inside myString
If you have a string like
'firstValue,secondValue,thirdValue,Value'
and you want to exactly search for 'Value', you have can transform the string in an array using
var content = 'firstValue,secondValue,thirdValue,Value';
var contentAsArray = content.split('');
var hasElement = contentAsArray.indexOf('Value') != -1;
Note that this trick assumes that your words are separated by ','.
In your case, i think you can use it like. So you do not have to convert it to string and back to array again.
data[1].indexOf('wordThatYouWant')
If you want to search only for whole words, so excluding "delight" when you are looking for "light", then you could use a regular expression with \b escapes inside.
Also, you'll need an additional loop, as your data structure has two dimensions.
Here is some code, turning the search words into a regular expression with \b:
function test() {
for ( var i = 0, l = groupKeywordsText.length; i < l; i++ ) {
var keywordToSearch = groupKeywordsText[i];
// Make regular expression for searching this keyword as whole word only.
// The keyword might need some escaping so it does not conflict
// with the regexp syntax:
var re = new RegExp('\\b' + keywordToSearch.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '\\b');
this["keywordGroup"+i] = [];
for(var j = 0; j < data.length; j++) {
for(var k = 0; k < data[j].length; k++) {
// test against the regular expression:
if (data[j][k] && data[j][k].match(re)) {
this["keywordGroup"+i].push(data[j]);
break;
}
}
}
}
return this;
}
// Sample data
var data = [
["Seed Keywords", "disconnectors" ,"EUR", "210" , "0.03" ,,,,,"N","Y"],
["ac", "hello", "who's there", "time to switch the lights off"],
["electricity", "high voltage", "danger"],
["volt and ampère", "a switch turned on"],
];
var groupKeywordsText = ["switch", "ac", "high", "switches", "disconnect", "voltage", "isolator"];
// Call
var result = test.bind({})();
// Show result in snippet
document.write('<pre>' + JSON.stringify(result, null, 4) + '</pre>');
I am brand new to programming and just getting started in an online program. The problem I am being presented with is:
Return a substring between two matching substrings.
The string I'm using is:
"Violets are blue, the sky is really blue"
I am trying to produce the substring between the two "blue"s.
That is:
", the sky is really "
This was one of my attempts which doesn't work. I was trying to slice it using indexOf() and lastIndexOf().
module.exports.substringBetweenMatches = function(text, searchString) {
return text.substring(function indexOf(searchString), function lastIndexOf(searchString);
};
module.exports.substringBetweenMatches("Violets are blue, the sky is really blue", "blue");
Any suggestions would be appreciated.
If the string will potentially have more than 2 "matches", you could split the string on the matches, then loop through and concat the strings back together:
var array = text.split(searchString); // split the given text, on the search term/phrase
if (array.length > 2) { // check to see if there were multiple sub-sections made
var string = "";
for (var i = 1; i < array.length; i++) { // start at 1, so we don't take whatever was before the first search term
string += array[i]; // add each piece of the array back into 1 string
}
return string;
}
return array[1];
This is pretty much the idea. I might have messed up the syntax for JavaScript in some places, but the logic is such:
function endsWith(a, s) {
var does_it_match = true;
var start_length = a.length()-s.length()-1;
for (int i=0; i<s.length(); i++) {
if (a[start_length+i]!=s.charAt(i)) {
does_it_match = false;
}
}
return does_it_match;
}
var buffer = new Array();
var return_string = "";
var read = false;
for (int i=0; i<string1.length(); i++) {
buffer.push(string1.charAt(1));
if (endsWith(buffer, "blue") && read==false) {
buffer = new Array();
read = true;
}
else if(endsWith(buffer, "blue") && read==true) {
break;
}
if (read==true) {
return_string = return_string.concat(string1.charAt(i));
}
}
return return_string;
I have stumbled upon this problem myself as a student on the Bloc.io bootcamp program. I stuck to the lessons string.substring() method and also string.indexOf() methods. Here is my go at this answer.
substringBetweenMatches = function(text, searchString) { //where text is your full text string and searchString is the portion you are trying to find.
var beginning = text.indexOf(searchString)+searchString.length; // this is the first searchString index location - the searchString length;
var ending = text.lastIndexOf(searchString); // this is the end index position in the string where searchString is also found.
return(text.substring(beginning,ending)); // the substring method here will cut out the text that doesn't belong based on our beginning and ending values.
};
If you are confused by my code, try:
console.log(beginning);
and
console.log(ending);
to see their values and how they would work with the substring() method.
Here is great reference to the substring() method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
Here is a JS Fiddle test. I use alert() instead of return. The concept is similar. https://jsfiddle.net/felicedeNigris/7nuhujx6/
I hope that is clear enough with my long comments on the sides?
Hope this helps.
I'm trying to create a code that will take a sentence as a param, split that sentence into an array of words and then create a loop that checks if any of theses word matches a word in some other arrays.
In the example below, I have a sentence that contains the word "ski". This means that the return value should be categories.type3.
How can I have make the loop check this? Could I have a function switching between different categories ? (ie : if a word is not in action, look in adventure and so on).
var categories = {
type1: "action",
type2: "adventure",
type3: "sport"
}
var Sentence = "This sentence contains the word ski";
var sport = ["soccer", "tennis", "Ski"];
var action = ["weapon", "explosions"];
var adventure = ["puzzle", "exploring"];
var myFreeFunc = function (Sentence) {
for (var i = 0; i < arrayLength; i++) {
if (typeArr[i] == word) {
}
}
}
You appear to want to know which categories match the sentence.
To start with, get rid of the meaningless type1 etc identifiers and re-arrange your fixed data into objects that directly represent the required data, specifically a Map of key/value pairs, where each key is a "category" name, and each value is a Set of keywords associated with that category:
var categories = new Map([
['action', new Set(['weapon', 'explosions'])],
['adventure', new Set(['puzzle', 'exploring'])],
['sport', new Set(['soccer', 'tennis', 'ski'])]
]);
[NB: Set and Map are new ES6 features. Polyfills are available]
You now have the ability to iterate over the categories map to get the list of categories, and over the contents of each category to find the key words:
function getCategories(sentence) {
var result = new Set();
var words = new Set(sentence.toLowerCase().split(/\b/g)); /* "/b" for word boundary */
categories.forEach(function(wordset, category) {
wordset.forEach(function(word) {
if (words.has(word)) {
result.add(category);
}
});
});
return result.values(); // NB: Iterator interface
}
NB: I've avoided for .. of because it's not possible to polyfill that, whereas Set.prototype.forEach and Map.prototype.forEach can be.
I would rewrite the code (you should always combine var statements).
I've added a small fiddle snippet, how i would rewrite the function. Just as an example, how you could iterate your data. Of course you should check out the other posts to optimise this code snipped ( e.g. fix for multiple spaces! ).
// make sure, your dictionary contains lower case words
var categories = {
action: ["soccer", "tennis", "ski"],
adventure: ["weapon", "explosions"],
sport: ["puzzle", "exploring"]
}
var myFreeFunc = function myFreeFunc(Sentence) {
// iterates over all keys on the categories object
for (var key in categories) {
// convert the sentence to lower case and split it on spaces
var words = Sentence.toLowerCase().split(' ');
// iterates the positions of the words-array
for (var wordIdx in words)
{
// output debug infos
console.log('test:', words[wordIdx], categories[key], categories[key].indexOf(words[wordIdx]) != -1, '('+categories[key].indexOf(words[wordIdx])+')');
// lets the array function 'indexOf' check for the word on position wordIdx in the words-array
if (categories[key].indexOf(words[wordIdx]) != -1 ) {
// output the found key
console.log('found', key);
// return the found key and stop searching by leaving the function
return key;
}
}//-for words
}//-for categories
// nothing found while iterating categories with all words
return null;
}
stripped down the function part snippet (no comments, no extra spaces, no console.log):
var myFreeFunc = function myFreeFunc(Sentence) {
for (var key in categories) {
var words = Sentence.toLowerCase().split(' ');
for (var wordIdx in words)
{
if (categories[key].indexOf(words[wordIdx]) != -1 ) {
return key;
}
}
}
return null;
}
Accumulated the topics covered in the comments
check if the Object really owns the property: obj.hasOwnProperty(prop)
split string by word bounds, as mentioned by Alnitak (using RegExp): /\b/g
collecting categories for multiple matching
Snippet:
var myFreeFunc = function myFreeFunc(Sentence) {
var result = []; // collection of results.
for (var key in categories) {
if (categories.hasOwnProperty(key)) { // check if it really is an owned key
var words = Sentence.toLowerCase().split(/\b/g); // splitting on word bounds
for (var wordIdx in words)
{
if (categories[key].indexOf(words[wordIdx]) != -1 ) {
result.push(key);
}
}
}
}
return result;
}
One simple way would be to do like this :
function determineCategory(word){
var dictionnary = {
// I assume here you don't need category1 and such
action: ["weapon", "explosions"],
aventure: ["puzzle", "exploring"],
sport: ["soccer", "tennis", "ski"]
}
var categories = Object.keys(dictionnary);
for(var i = 0; i<categories.length; i++){
for(var j = 0; j<categories[i].length;j++){
var wordCompared = dictionnary[categories[i]][j];
if(wordCompared == word){
return categories[i];
}
}
}
return "not found";
}
var sentence = "This sentence contains the word ski";
var words = sentence.split(" "); // simple separation into words
var result = [];
for(var i=0; i<words.length; i++){
result[i] = determineCategory(words[i]);
}
A few notes on this approach :
it needs you to change your existing structure (I don't know if its possible)
it doesn't do much for your sentence splitting (just using the white space). For more clever approach, see Alnitak's answer, or look for tokenization/lemmatization methods.
it is up to you to determine what to do when a word doesn't belong to a category (right now, it just stores "not found".
I'm trying to break up a string like this one:
fname=bill&mname=&lname=jones&addr1=This%20House&...
I want to end up with an array indexed like this
myarray[0][0] = fname
myarray[0][1] = bill
myarray[1][0] = mname
myarray[1][1] =
myarray[2][0] = lname
myarray[2][1] = jones
myarray[3][0] = addr
myarray[3][1] = This House
The url is quite a bit longer than the example. This is what I've tried:
var
fArray = [],
nv = [],
myarray = [];
fArray = fields.split('&');
// split it into fArray[i]['name']="value"
for (i=0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push(nv[0],nv[1]);
nv.length = 0;
}
The final product is intended to be in 'myarray' and it is, except that I'm getting a one dimensional array instead of a 2 dimensional one.
The next process is intended to search for (for example) 'lname' and returning the index of it, so that if it returned '3' I can then access the actual last name with myarray[3][1].
Does this make sense or am I over complicating things?
Your line myarray.push(nv[0],nv[1]); pushes two elements to the array myarray, not a single cell with two elements as you expect (ref: array.push). What you want is myarray.push( [nv[0],nv[1]] ) (note the brackets), or myarray.push(nv.slice(0, 2)) (ref: array.slice).
To simplify your code, may I suggest using Array.map:
var q = "foo=bar&baz=quux&lorem=ipsum";
// PS. If you're parsing from a-tag nodes, they have a property
// node.search which contains the query string, but note that
// it has a leading ? so you want node.search.substr(1)
var vars = q.split("&").map(function (kv) {
return kv.split("=", 2);
});
For searching, I would suggest using array.filter:
var srchkey = "foo";
var matches = vars.filter(function (v) { return v[0] === srchkey; });
NB. array.filter will always return an array. If you always want just a single value, you could use array.some or a bespoke searching algorithm.
for (var i = 0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push([nv[0],nv[1]]);
}
nv.length = 0; is not required, since you're setting nv in each iteration of the for loop.
Also, use var i in the for-loop, otherwise, you're using / assigning a global variable i, that's asking for interference.