I am trying find out the matching element of an array for a given string.
var array = ["CODE1", "CODE2", "CODE3", "CODE4", "CODE5", "CODE6"];
var text = "alsdjklfjaaCODE2ladkslfj";
var resultCode;
for (var i in array) {
if (text.indexOf(array[i]) > -1) {
resultCode = array[i];
}
}
console.log(resultCode);
But I felt that it is not efficient way to iterate through array as that array was little big. Is there any alternative algorithm for my problem.
As of ES6, you can use Array.prototype.find and Array.prototype.includes
var array = ["CODE1", "CODE2", "CODE3", "CODE4", "CODE5", "CODE6"],
text = "alsdjklfjaaCODE2ladkslfj";
var resultCode = array.find(a => text.includes(a));
document.write(resultCode);
You can use Array.prototype.some()
The some() method tests whether some element in the array passes the test implemented by the provided function.
if you expect only one match in the string. The iteration stops if the callback returns true.
var array = ["CODE1", "CODE2", "CODE3", "CODE4", "CODE5", "CODE6"],
text = "alsdjklfjaaCODE2ladkslfj",
resultCode;
array.some(function (a) {
if (~text.indexOf(a)) {
resultCode = a;
return true;
}
});
document.write(resultCode);
Related
I am trying to filter some data from an array in a JSON file, based on an input of the form string1, string1,string2, string1,string2,string3 etc., that is, some strings separated by a ,.
What I'm trying to do:
let arrInput = document.getElementById('inputBox').val.split(',');
for(let i = 0; i < arrToFilter.length; i++){
if(.........what to write here?...........){
arrOutput.push(arrToFilter[i]);
}
}
return arrOutput;
If the arrInput had a fixed length, I could accomplish this using indexOf != -1 for each element in arrInput, but here, since the length of arrInput is variable, how can I check if at least one of the strings present in arrInput is also present as a substring in arrToFIlter[i]?
Edit:
Example:
Let arrToFilter be ["abcqwer", "pizza", "definition", "abcdef", "example"]
Case 1 :
Say the input entered (in an <input> element) is abc,def.
For this, the arrOutput should be ["abcqwer", "definition", "abcdef"]
Case 2:
Say the input entered is abc
Expected output : ["abcqwer", "abcdef"]
Simple way is using some and filter,
var string = 'ad,kk,sb';
var array = ['adik', 'klop', 'pp'];
var stringers = string.split(',');
var result = array.filter((arr) => {
var isPresent = stringers.some(stringer => arr.includes(stringer));
return isPresent ? true : false;
});
console.log(result);
You need to iterate both arrays
let arrToFilter = ['abcqwer', 'pizza', 'definition', 'abcdef', 'example'];
let arrOutput = [];
let arrInput = document.getElementById('inputBox').value.split(',');
arrToFilter.forEach(filter => {
arrInput.forEach(input => {
if (!!input && filter.includes(input)) {
arrOutput.push(filter);
}
});
});
// distinct the output
return arrOutput.filter((v, i, a) => i === a.indexOf(v));
What is the most efficient way to find out if a JavaScript array contains substring of a given string?
For example in case I have a JavaScript array
var a = ["John","Jerry","Ted"];
I need the condition which returns true when I compare the above array against the string:
"John Elton"
For ES6:
var array = ["John","Jerry","Ted"];
var strToMatch = "John Elton"
array.some(el => strToMatch.includes(el))
You can use .some() and .includes() methods:
let arr = ["John","Jerry","Ted"];
let str = "John Elton";
let checker = (arr, str) => arr.some(s => str.includes(s));
console.log(checker(arr, str));
In case you cannot use ES6:
let arr = ["John","Jerry","Ted"];
let str = "John Elton";
var match = arr.some(function (name) {
return str.indexOf(name) > -1;
});
console.log(match);
So I'm a little stuck as to why this isn't working. I'm trying to remove all of the empty strings in an array and it keeps giving me back an array that is just one empty string. Any ideas?
function splitNames(){
var names = document.getElementById("1").value.split("\n");
for(var i = 0; i<=names.length; i++){
if(names[i]==""){
names = names.splice(i, 1);
console.log(names);
}
}
console.log(names);
}
The string would look like this by the way.
Hi
Hello
(remove this one)
Bonjour
blah
(remove this one)
(remove this one)
blah
The array comes out to this ["Hi", "Hello","",...]
Perhaps the simplest way to do this is to use the filter function and search for truthy values. By default, empty strings are false.
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
var strings = ["zebras", "trees", "forests", "", "hi", "wizards", "", "", "lizards"];
strings = strings.filter((e) => e);
console.log(strings);
It's important to note that empty strings by default are false. However, strings that contain only whitespace characters are true. In that scenario, my example would not work and you would have to do this
strings.filter((e) => e.trim());
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
function splitNames(){
// var names = document.getElementById("1").value.split("\n");
var names = "Hi\nHello\n \nGoodBye".split("\n");
var filteredNames = names.filter(function(item){
return item.trim() !== "";
});//filter
return filteredNames;
}//splitNames()
console.log( splitNames() );
Create a new array and push what you need.
function splitNames(){
var names = document.getElementById("1").value.split("\n");
var newArr = [];
for(var i = 0; i<=names.length; i++){
if(names[i]){
newArr.push(names[i]);
}
}
return newArr.join('\n');
//console.log(names);
}
try it:
function splitNames(){
var names = document.getElementById("1").value.split("\n");
var newArr = names.filter(function(name){
return name!=="";
});
return newArr;
}
Given an array of strings:
x = ["banana","apple","orange"]
is there a built in shortcut for performing wildcard searches?
ie., maybe
x.indexOf("*na*") //returns index of a string containing the substring na
Expanding on Pim's answer, the correct way to do it (without jQuery) would be this:
Array.prototype.find = function(match) {
return this.filter(function(item){
return typeof item == 'string' && item.indexOf(match) > -1;
});
}
But really, unless you're using this functionality in multiple places, you can just use the existing filter method:
var result = x.filter(function(item){
return typeof item == 'string' && item.indexOf("na") > -1;
});
The RegExp version is similar, but I think it will create a little bit more overhead:
Array.prototype.findReg = function(match) {
var reg = new RegExp(match);
return this.filter(function(item){
return typeof item == 'string' && item.match(reg);
});
}
It does provide the flexibility to allow you to specify a valid RegExp string, though.
x.findReg('a'); // returns all three
x.findReg("a$"); // returns only "banana" since it's looking for 'a' at the end of the string.
Extending on #Shmiddty's answer, here are useful JavaScript ideas:
Extend Array with a new method: Array.prototype.method = function(arg) { return result; }
Filter arrays using: Array.filter(function(e) { return true|false; })
Apply formula to elements in an array: Array.map(function(e) { return formula(e); })
Use regular expressions: either /.*na.*/ or new Regex('.*na.*')
Use regular expressions to match: let result = regex.test(input);
Use Array.prototype.reduce to aggergate a result after running a function on every element of an array
i.e. I prefer the input argument to be a regex, so, it gives you either:
A short but universal pattern matching input,
e.g. contains, starts with, ends width, as well as more sophisticated matches
The ability to specify an input pattern as a string
SOLUTION 1: filter, test, map and indexOf
Array.prototype.find = function(regex) {
const arr = this;
const matches = arr.filter( function(e) { return regex.test(e); } );
return matches.map(function(e) { return arr.indexOf(e); } );
};
let x = [ "banana", "apple", "orange" ];
console.log(x.find(/na/)); // Contains 'na'? Outputs: [0]
console.log(x.find(/a/)); // Contains 'a'? Outputs: [0,1,2]
console.log(x.find(/^a/)); // Starts with 'a'? Outputs: [1]
console.log(x.find(/e$/)); // Ends with 'e'? Outputs: [1,2]
console.log(x.find(/pear/)); // Contains 'pear'? Outputs: []
SOLUTION 2: reduce, test
Array.prototype.find = function(regex) {
return this.reduce(function (acc, curr, index, arr) {
if (regex.test(curr)) { acc.push(index); }
return acc;
}, [ ]);
}
let x = [ "banana", "apple", "orange" ];
console.log(x.find(/na/)); // Contains 'na'? Outputs: [0]
console.log(x.find(/a/)); // Contains 'a'? Outputs: [0,1,2]
console.log(x.find(/^a/)); // Starts with 'a'? Outputs: [1]
console.log(x.find(/e$/)); // Ends with 'e'? Outputs: [1,2]
console.log(x.find(/pear/)); // Contains 'pear'? Outputs: []
You can extend the array prototype to find matches in an array
Array.prototype.find = function(match) {
var matches = [];
$.each(this, function(index, str) {
if(str.indexOf(match) !== -1) {
matches.push(index);
}
});
return matches;
}
You can then call find on your array like so
// returns [0,3]
["banana","apple","orange", "testna"].find('na');
using regex can do this in javascript
var searchin = item.toLowerCase();
var str = columnId;
str = str.replace(/[*]/g, ".*").toLowerCase().trim();
return new RegExp("^"+ str + "$").test(searchin);
In addition to everything else that has been said, you can do this:
var x = ["banana", "apple", "orange"];
var y = [];
for (var i in x) {
if (x[i].indexOf('na') > -1) {
y.push(i);
}
}
Results: y = [0]
Solving another array manipulation, and I'm taking longer than usual to solve this. I need help in combining array values:
var array1 = ["alpha|LJ", "bravo|MH", "charlie|MH", "delta|MF",
"echo|16", "{foxtrot}|GG", "{golf}|HS"];
var array2 = ["charlie-{golf}-{foxtrot}", "echo-{golf}"]; //some templates
such that the final array be:
final_array = ["alpha-LJ", "bravo-MH", "charlie-HS-GG-MH", "delta-MF",
"echo-HS-16"];
To make it clear how I arrived with the final_array, alpha, bravo and delta only got their "|" replaced with "-" since they are not found on my array2 template. charlie and echo got the template so the respective values of the {} were replaced based on array1. Array1 honestly is not the best key:value relationship that I could come up for now.
Here are some requirementL:
* Anything in array1 with {} braces are not meant to be templated.
* Keywords in array2 will always have a matching value in array1.
I've read about jquery .map() and thinking that it is achievable using this, maybe together with Regexp. Hope you'll utilize these. Also, if it helps, final_array can be of any order.
I really need to up my knowledge on these two topics... :|
Thank you in advance.
Edit: Updated to match your output and comment some of the madness. This doesn't feel like it's the most efficient, given the split() done to values at the start and then again at the end...but it works.
function funkyTransform( values, templates ){
// Make a copy of the array we were given so we can mutate it
// without rudely changing something passed to our function.
var result = values.concat();
// Map {value} entries for later lookup, and throw them out of the result
var valueMap = {};
for (var i=result.length-1;i>=0;--i){
var pair = result[i].split('|');
if (pair[0][0]=="{"){
valueMap[pair[0]] = pair[1];
result.splice(i,1); // Yank this from the result
}
}
console.log(valueMap);
// {
// "{foxtrot}": "GG",
// "{golf}": "HS"
// }
// Use the value map to replace text in our "templates", and
// create a map from the first part of the template to the rest.
// THIS SHOULD REALLY SCAN THE TEMPLATE FOR "{...}" PIECES
// AND LOOK THEM UP IN THE MAP; OOPS O(N^2)
var templateMap = {};
for (var i=templates.length-1;i>=0;--i){
var template = templates[i];
for (var name in valueMap){
if (valueMap.hasOwnProperty(name)){
template = template.replace(name,valueMap[name]);
}
}
var templateName = template.split('-')[0];
templateMap[ templateName ] = template.slice(templateName.length+1);
}
console.log(templateMap);
// {
// "charlie": "HS-GG",
// "echo": "HS"
// }
// Go through the results again, replacing template text from the templateMap
for (var i=result.length-1;i>=0;--i){
var pieces = result[i].split('|');
var template = templateMap[pieces[0]];
if (template) pieces.splice(1,0,template);
result[i] = pieces.join('-');
}
return result;
}
var output = funkyTransform( array1, array2 );
console.log(output);
// ["alpha-LJ", "bravo-MH", "charlie-HS-GG-MH", "delta-MF", "echo-HS-16"]
This managed to get your desired output, though I made a few assumptions:
Anything in array1 with {} braces are not meant to be templated.
Keywords in array2 will always have a matching value in array1 (this can easily be changed, but not sure what your rule would be).
Code:
// This is the main code
var final_array = $.map(array1, function (item) {
var components = item.split('|');
// Ignore elements between {} braces
if (/^\{.*\}$/.test(components[0])) return;
components[0] = template(components[0]);
return components.join('-');
});
// Helper to lookup array2 for a particular string and template it
// with the values from array1
function template(str) {
var index = indexOfMatching(array2, str, '-');
if (index == -1) return str;
var components = array2[index].split('-');
var result = [str];
for (var i = 1; i < components.length; i++) {
result.push(array1[indexOfMatching(array1, components[i], '|')]
.split('|')[1]);
}
return result.join('-');
}
// Helper to for looking up array1 and array2
function indexOfMatching(array, target, separator) {
for (var i = 0; i < array.length; i++) {
if (array[i].split(separator)[0] === target) return i;
}
return -1;
}