Split String into Array with RegEx Pattern - javascript

I have a string that I want to split into an array. The string looks like this:
'O:BED,N:KET,OT,N:JAB,FA,O:RPT,'
The string can contain any number of objects eg
'O:BED,N:KET,OT,N:JAB,FA,O:RPT,X:BLA,GTO'
I want to split this string on the instance of \w: eg O:
So I'll end up with array like this:
['O:BED','N:KET, OT','N:JAB,FA','O:RPT']
I am using the following code:
var array = st.split(/^(\w:.+)(?=\w:)/g);
However I end up with array like this :
['','O:BED,N:KET,OT,N:JAB,FA,','O:RPT,']
It seems the regex is being greedy, what should I do to fix it?
Note I am using angularjs and eventually I want to end up with this :
var objs = [
{type:O,code: BED, suf: ''},
{type:N, code: KET, suf: OT},
{type:N, code: JAB, suf: FA},
{type:O, code: RPT, suf: ''}
]

It would be much easier if your string is formatted properly. But still we can achieve the task with extra effort. Hope the below code works for you.
var str = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,X:BLA,GTO';
var a = str.split(',');
var objs = [], obj, item, suf;
for(var i=0; i<a.length;){
item = a[i].split(':');
if(a[i+1] && a[i+1].indexOf(':') == -1){
suf = a[i+1];
i++;
}else{
suf = "";
}
obj = {
type: item[0],
code: item[1],
suf: suf
};
objs.push(obj);
i++;
}
console.log(objs);

You can use the RegExp.prototype.exec method to obtain successive matches instead of splitting the string with a delimiter:
var myStr = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
var myRe = /([^,:]+):([^,:]+)(?:,([^,:]+))??(?=,[^,:]+:|,?$)/g;
var m;
var result = [];
while ((m = myRe.exec(myStr)) !== null) {
result.push({type:m[1], code:m[2], suf:((m[3])?m[3]:'')});
}
console.log(result);

You want to do a string match and then iterate over that.
Full example inside AngularJS: http://jsfiddle.net/184cyspg/1/
var myString = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
$scope.myArray = [];
var objs = myString.match(/([A-Z])\:([A-Z]*)\,([A-Z]?)/g);
objs.forEach(function (entry) {
var obj = entry.replace(',', ':');
obj = obj.split(':');
$scope.myArray.push({type: obj[0], code: obj[1], suf: obj[2]});
});

I love regular expressions :)
This will match each object of your string, if you want to use the global flag and exec() through all the matches:
(\w):(\w+)(?:,((?!\w:)\w+))?
The only real trick is to only treat the next bit after the comma as the suffix to this one if it doesn't look like the type of the next.
Each match captures the groups:
type
code
suf
If you just want to split as you said, then the solution to your greedy problem is to tell it to split on commas which are followed by those matching objects, eg:
,(?=(\w):(\w+)(?:,((?!\w:)\w+))?)

The following does not solve your regex issue however is an alternative approach to introduce underscorejs to handle from simple to more complex operations. Although an overkill in this case;
// ie. input string = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
.controller('AppCtrl', [function() {
/**
* Split by comma then (chain) eval each (map)
* element that (if-else) contains '0:' is pushed
* into array as a new element, otherwise concat element
*
* :#replace hardcoded values with params
*
* #param String string - a string to split
* #param String prefix - prefix to determine start of new array element ie. '0:'
* #param String delimiter - delimiter to split string ie ','
* #return Array array of elements by prefix
*/
$scope.splitter = function(string) {
var a = [];
var tmp = "";
_.chain(string.split(','))
.map(function(element) {
if(element.indexOf('O:') >= 0) {
element += tmp;
a.push(element);
tmp = "";
} else {
tmp += element;
}
});
return a;
};
}]);
Output:
array: Array[2]
0: "O:BED"
1: "O:RPTN:KETOTN:JABFA"
length: 2
Updated: Just read your requirements on Objects. underscorejs allows chaining operations. For example, the code above could be tweaked to handle Objects, chained to .compact().object().value() to produce output as Object k:v pairs;
Hope this helps.

Related

How to convert JavaScript object into LITERAL string?

If I have the object literal:
{a: "hello"}
Is there a Javascript function to convert this object into a literal string, so that the output would be the literal syntax:
'{a: "hello"}'
With JSON.stringify the output would be
'{"a": "hello"}'
You can do it with JSON.stringify and then with String.replace like follows:
var jsObj =
{
abc: "hello",
bca: "allo",
cab: "dd:cc",
d: ["hello", "llo", "dd:cc"],
e: {abc: "hello", bca: "allo", cab: "dd:cc"}
};
function format(obj)
{
var str = JSON.stringify(obj, 0, 4),
arr = str.match(/".*?":/g);
for(var i = 0; i < arr.length; i++)
str = str.replace(arr[i], arr[i].replace(/"/g,''));
return str;
}
console.log(format(jsObj));
JavaScript has no built-in functions that will convert an object to a string representation of it which either:
Uses identifiers instead of strings for property names
Represents the original syntax used to create the object
You could write your own function for the former (at least when the property name can be represented as a literal) but the latter is impossible as JavaScript stores no information about the source code used to create the object in the first place.
Ok just for fun...roll your own?
const stringify = (obj) => {
// Iterate over keys, reducing to a string
let str = Object.keys(obj).reduce((acc, cur) => {
let next = `${cur}: "${obj[cur]}"`;
return acc
? `${acc}, ${next}`
: `{${next}`;
}, '');
// Return, appending final '}'
return `${str}}`;
}
document.write(stringify({
foo:1,
bar:'seat'
}));
That said, your exact requirements aren't clear so I'm not sure this will meet them. But it might be a starting point if there's no native solution that works.
It does convert it to the literal syntax. You are able to create objects with multiple forms of syntax. Both of the following object declarations are valid:
var a = {a: "a"}
var b = {"b": "b"}
If you want to remove the "" around the key you should be able to match them with the following regex /\"(.*?)\":/g and replace them with something like this:
function reformat(str) {
var myRegexp = /\"(.*?)\":/g;
match = myRegexp.exec(str);
while (match != null) {
str = str.replace(match[0], match[1] + ":");
match = myRegexp.exec(str);
}
return str;
}
Hope that helps :)

Allowing commas to follow through when converting array to string

I have an array of character with commas separating them. I need to split an array but retain my comma inbetween each character.
See below for an example array:
var myArray = [a,,,b,c,d,,,]
There's a comma in there between the characters "a" and "b". I need to retain the comma when converting the array to a string.
The output string needs to resemble this:
a,bcd,
This is what i'm currently doing to retain the commas:
myArray.toString().replace(/,/g, "");
The Array's toString() method basically does a join(",") which is why you are getting the extra commas in your string.
Instead use join("") if you want to join the elements without the delimiter being added as part of the string
var myArray = ["a",",","b","c","d",",",]
document.body.innerText = myArray.join("");
How about you use :
var myArray = [a,,,b,c,d,,,];
var str = myArray.join();
This will give a string of array elements, preserving the commas.
if you want it to maintain the centre comma you should create your array as
var myArray = [a,",",b,c,d,",",];
this will then treat the middle comma in the set of 3 as a string containing that character rather than the array seperator
You could change your regex, to replace item,item for item item.
myArray.toString().replace(/([a-z,]),([a-z,])/g, "$1$2")
Basically you have a sparse array and want to extract only filled values and convert it to string ? Here is one, probably not the best, solution :
var myArray = ['a',',',',','b',',','c']
var resultArray = [];
for(var i = 0; i < myArray.length; i++){
if(myArray[i] !== ','){// allow 0, false, null values, but not undefined
resultArray.push(myArray[i]);
}
}
console.log(resultArray);
Working plnkr : http://plnkr.co/edit/55T6PGI9DuTlvy6k88hr?p=preview, check the console of your broswer.
If this is an actual array of strings and you wanted only those with actual values, you could use the filter() function to filter out any non-undefined ones :
// Your example array
var input = ['a',,,'b','c','d',,,];
// Remove any undefined elements
var output = input.filter(function(e){ return e; }); // yields ['a','b','c','d']
You could then use the join() function to create a string with your elements :
var result = output.join(); // yields "a,b,c,d"
Example Snippet
var input = ['a',,,'b','c','d',,,];
document.write('INPUT: ' + input + '<br />');
var output = input.filter(function(e){ return e; });
document.write('OUTPUT: ' + output);

javascript function takes string and returns array

First I have an array that has two strings in it.
var Array = ["firstName lastName" , "anotherString"]
I would like to create a function that takes in a string as a parameter and returns an array by breaking up the input string into individual words. So the output in this example would be ["firstName", "lastName"] ?
I know it would look something like this
var newFun = function(string) {
return string[0] // than do something else
}
Help is greatly appreciated!
So simple, use the String.prototype.split method to split strings into array list.
MDN:
The split() method splits a String object into an array of strings by separating the string into substrings.
return str.split(' ');
#Christoph:
You are using some very bad conventions here.
var Array
function (string)
Array is a predefined class in javascript and string is pretty close to the predefined class String, so just avoid using them completely.
var arr;
function (str)
Short Method: splits a string with multiple words, handles funky strings that String.prototype.split(' ') can't handle like " firstName Lastname" or just "firstName Lastname". returns an Array
function smartSplit (str) {
// .trim() remove spaces surround the word
// /\s+/ split multiple spaces not just one ' '
return str.trim().split(/\s+/);
}
Test Case:
// case: split(' ');
console.log(" firstName lastName".split(' '));
// result: ["", "", "", "firstName", "", "", "", "lastName"]
// case: split(/\s+/)
console.log(" firstName lastName".split(/\s+/));
// result: ["", "firstName", "lastName"]
// case: .trim().split(/\s+/)
console.log(smartSplit(" firstName lastName"));
// result: ["firstName", "lastName"]
Complete Method: same as smartSplit except for it expects an Array as a parameter instead of a String
function smartSplitAll (strArr) {
var newArr = [];
for (var i = 0; i < strArr.length; i++) {
// expecting string array
var str = strArr[i].trim();
// split the string if it has multiple words
if (str.indexOf(' ') > -1)
newArr = newArr.concat(str.split(/\s+/));
else
newArr.push(str);
}
return newArr;
}
console.log(smartSplitAll(["firstName lastName", "anotherString"]);
// result: ["firstName", "lastName", "anotherString"]
Code lives here: http://jsfiddle.net/8xgzkz16/
The index of [0] is actually the first character of the string.
Do this:
var myString = "My Name";
var splitResult = myString.split(" ");
Will result in:
["My", "Name"]
You could do something like this using the split method from the object String
var newFun = function(string) {
return string[0].split(" ");
}
VoilĂ  !
You can use the string split method:
function splitString(input) {
return input.split(" ");
}
Several comments on your code:
1) the function you are looking for is String.prototype.split:
var string = "firstName lastName";
string.split(" ");
// returns an array: ["firstName","lastName"]
2) don't call your array Array. This is a "reserved word"* for the Array prototype! You are overwriting the prototype, if you do so!
3) Keep the naming of your parameters consistent. This way you avoid error like you did in your code. Handing over an array and call the parameter string is a bad idea. string[0] returns the first symbol of the string, array[0] the first element of your array. Also, name the function appropriately.
Your code should look like this:
var array = ["firstName lastName" , "anotherString"];
function returnSplitString(string){
return string.split(" ");
}
var splitStringArray = returnSplitString(array[0]);
* In the strict technical sense it is not, because you CAN name your variable that way, however it's a bad idea to do so.
var newFun = function(str) {
return str.split(" ");
}
This splitter will take any array with mixed string (strings with spaces and without spaces) and split them in a linear array.
var splitter = (array) => {
return array.reduce((acc, value) => {
return /\s/.test(value) ? acc.concat(value.trim().split(' ')) : acc.concat(value) ;
}, []);
}
console.log(splitter(["There is proper space", "ThereIsNoSpace"]));
will output:
['There', 'is', 'proper', 'space', 'thereisnospace']

jquery grep, fitlering with regex

I will start this question with the statement that I'm really bad with regex.
Said this, I wonder if possible to filter an array using jquery $.grep, match strings with an specific string, something like this:
var a = ["ABC:12", "xx:ABC:2", "ASD:3", "xx:ASD:5"];
var s = a.split(",");
var array = $.grep(s, function(x, y) {
return ??????;
});
so after applying $.grep or any other function which could help, i will need the after ":" number of those with ABC, so my new array would be:
array[12, 2];
Any help with this??? I would really appreciate!
$.grep only select elements of an array which satisfy a filter function.
You need additional step to $.map all numbers from grepped array.
var a = ["ABC:12", "xx:ABC:2", "ASD:3", "xx:ASD:5"];
var b = $.grep(a, function(item) {
return item.indexOf("ABC:") >= 0;
});
var array = $.map(b, function(item) {
return item.split(":").pop();
});
Try
var a = ["ABC:12", "xx:ABC:2", "ASD:3", "xx:ASD:5"];
// map array ,
// test array items for "ABC" string ,
// filter `Number` in strings containing "ABC" ,
// return filtered Numbers , in newly mapped array
var s = $.map(a, function(n) {
return (/ABC/.test(n) ? Number(n.split(":").filter(Number)) : null)
}); // [12, 2]

How to check if a string contains text from an array of substrings in JavaScript?

Pretty straight forward. In javascript, I need to check if a string contains any substrings held in an array.
There's nothing built-in that will do that for you, you'll have to write a function for it, although it can be just a callback to the some array method.
Two approaches for you:
Array some method
Regular expression
Array some
The array some method (added in ES5) makes this quite straightforward:
if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
// There's at least one
}
Even better with an arrow function and the newish includes method (both ES2015+):
if (substrings.some(v => str.includes(v))) {
// There's at least one
}
Live Example:
const substrings = ["one", "two", "three"];
let str;
// Setup
console.log(`Substrings: ${substrings}`);
// Try it where we expect a match
str = "this has one";
if (substrings.some(v => str.includes(v))) {
console.log(`Match using "${str}"`);
} else {
console.log(`No match using "${str}"`);
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (substrings.some(v => str.includes(v))) {
console.log(`Match using "${str}"`);
} else {
console.log(`No match using "${str}"`);
}
Regular expression
If you know the strings don't contain any of the characters that are special in regular expressions, then you can cheat a bit, like this:
if (new RegExp(substrings.join("|")).test(string)) {
// At least one match
}
...which creates a regular expression that's a series of alternations for the substrings you're looking for (e.g., one|two) and tests to see if there are matches for any of them, but if any of the substrings contains any characters that are special in regexes (*, [, etc.), you'd have to escape them first and you're better off just doing the boring loop instead. For info about escaping them, see this question's answers.
Live Example:
const substrings = ["one", "two", "three"];
let str;
// Setup
console.log(`Substrings: ${substrings}`);
// Try it where we expect a match
str = "this has one";
if (new RegExp(substrings.join("|")).test(str)) {
console.log(`Match using "${str}"`);
} else {
console.log(`No match using "${str}"`);
}
// Try it where we DON'T expect a match
str = "this doesn't have any";
if (new RegExp(substrings.join("|")).test(str)) {
console.log(`Match using "${str}"`);
} else {
console.log(`No match using "${str}"`);
}
One line solution
substringsArray.some(substring=>yourBigString.includes(substring))
Returns true\false if substring exists\does'nt exist
Needs ES6 support
var yourstring = 'tasty food'; // the string to check against
var substrings = ['foo','bar'],
length = substrings.length;
while(length--) {
if (yourstring.indexOf(substrings[length])!=-1) {
// one of the substrings is in yourstring
}
}
function containsAny(str, substrings) {
for (var i = 0; i != substrings.length; i++) {
var substring = substrings[i];
if (str.indexOf(substring) != - 1) {
return substring;
}
}
return null;
}
var result = containsAny("defg", ["ab", "cd", "ef"]);
console.log("String was found in substring " + result);
For people Googling,
The solid answer should be.
const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
// Will only return when the `str` is included in the `substrings`
}
Here's what is (IMO) by far the best solution. It's a modern (ES6) solution that:
is efficient (one line!)
avoids for loops
unlike the some() function that's used in the other answers, this one doesn't just return a boolean (true/false)
instead, it either returns the substring (if it was found in the array), or returns undefined
goes a step further and allows you to choose whether or not you need partial substring matches (examples below)
Enjoy!
const arrayOfStrings = ['abc', 'def', 'xyz'];
const str = 'abc';
const found = arrayOfStrings.find(v => (str === v));
Here, found would be set to 'abc' in this case. This will work for exact string matches.
If instead you use:
const found = arrayOfStrings.find(v => str.includes(v));
Once again, found would be set to 'abc' in this case. This doesn't allow for partial matches, so if str was set to 'ab', found would be undefined.
And, if you want partial matches to work, simply flip it so you're doing:
const found = arrayOfStrings.find(v => v.includes(str));
instead. So if str was set to 'ab', found would be set to 'abc'.
Easy peasy!
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = 0, len = arr.length; i < len; ++i) {
if (str.indexOf(arr[i]) != -1) {
// str contains arr[i]
}
}
edit:
If the order of the tests doesn't matter, you could use this (with only one loop variable):
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = arr.length - 1; i >= 0; --i) {
if (str.indexOf(arr[i]) != -1) {
// str contains arr[i]
}
}
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)
For full support ;)
For full support (additionally to #ricca 's verions).
wordsArray = ['hello', 'to', 'nice', 'day']
yourString = 'Hello. Today is a nice day'.toLowerCase()
result = wordsArray.every(w => yourString.includes(w))
console.log('result:', result)
If the array is not large, you could just loop and check the string against each substring individually using indexOf(). Alternatively you could construct a regular expression with substrings as alternatives, which may or may not be more efficient.
Javascript function to search an array of tags or keywords using a search string or an array of search strings. (Uses ES5 some array method and ES6 arrow functions)
// returns true for 1 or more matches, where 'a' is an array and 'b' is a search string or an array of multiple search strings
function contains(a, b) {
// array matches
if (Array.isArray(b)) {
return b.some(x => a.indexOf(x) > -1);
}
// string match
return a.indexOf(b) > -1;
}
Example usage:
var a = ["a","b","c","d","e"];
var b = ["a","b"];
if ( contains(a, b) ) {
// 1 or more matches found
}
This is super late, but I just ran into this problem. In my own project I used the following to check if a string was in an array:
["a","b"].includes('a') // true
["a","b"].includes('b') // true
["a","b"].includes('c') // false
This way you can take a predefined array and check if it contains a string:
var parameters = ['a','b']
parameters.includes('a') // true
Best answer is here:
This is case insensitive as well
var specsFilter = [.....];
var yourString = "......";
//if found a match
if (specsFilter.some((element) => { return new RegExp(element, "ig").test(yourString) })) {
// do something
}
const str = 'Does this string have one or more strings from the array below?';
const arr = ['one', 'two', 'three'];
const contains = arr.some(element => {
if (str.includes(element)) {
return true;
}
return false;
});
console.log(contains); // true
Not that I'm suggesting that you go and extend/modify String's prototype, but this is what I've done:
String.prototype.includes()
String.prototype.includes = function (includes) {
console.warn("String.prototype.includes() has been modified.");
return function (searchString, position) {
if (searchString instanceof Array) {
for (var i = 0; i < searchString.length; i++) {
if (includes.call(this, searchString[i], position)) {
return true;
}
}
return false;
} else {
return includes.call(this, searchString, position);
}
}
}(String.prototype.includes);
console.log('"Hello, World!".includes("foo");', "Hello, World!".includes("foo") ); // false
console.log('"Hello, World!".includes(",");', "Hello, World!".includes(",") ); // true
console.log('"Hello, World!".includes(["foo", ","])', "Hello, World!".includes(["foo", ","]) ); // true
console.log('"Hello, World!".includes(["foo", ","], 6)', "Hello, World!".includes(["foo", ","], 6) ); // false
building on T.J Crowder's answer
using escaped RegExp to test for "at least once" occurrence, of at least one of the substrings.
function buildSearch(substrings) {
return new RegExp(
substrings
.map(function (s) {return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');})
.join('{1,}|') + '{1,}'
);
}
var pattern = buildSearch(['hello','world']);
console.log(pattern.test('hello there'));
console.log(pattern.test('what a wonderful world'));
console.log(pattern.test('my name is ...'));
Drawing from T.J. Crowder's solution, I created a prototype to deal with this problem:
Array.prototype.check = function (s) {
return this.some((v) => {
return s.indexOf(v) >= 0;
});
};
Using underscore.js or lodash.js, you can do the following on an array of strings:
var contacts = ['Billy Bob', 'John', 'Bill', 'Sarah'];
var filters = ['Bill', 'Sarah'];
contacts = _.filter(contacts, function(contact) {
return _.every(filters, function(filter) { return (contact.indexOf(filter) === -1); });
});
// ['John']
And on a single string:
var contact = 'Billy';
var filters = ['Bill', 'Sarah'];
_.every(filters, function(filter) { return (contact.indexOf(filter) >= 0); });
// true
If you're working with a long list of substrings consisting of full "words" separated by spaces or any other common character, you can be a little clever in your search.
First divide your string into groups of X, then X+1, then X+2, ..., up to Y. X and Y should be the number of words in your substring with the fewest and most words respectively. For example if X is 1 and Y is 4, "Alpha Beta Gamma Delta" becomes:
"Alpha" "Beta" "Gamma" "Delta"
"Alpha Beta" "Beta Gamma" "Gamma Delta"
"Alpha Beta Gamma" "Beta Gamma Delta"
"Alpha Beta Gamma Delta"
If X would be 2 and Y be 3, then you'd omit the first and last row.
Now you can search on this list quickly if you insert it into a Set (or a Map), much faster than by string comparison.
The downside is that you can't search for substrings like "ta Gamm". Of course you could allow for that by splitting by character instead of by word, but then you'd often need to build a massive Set and the time/memory spent doing so outweighs the benefits.
convert_to_array = function (sentence) {
return sentence.trim().split(" ");
};
let ages = convert_to_array ("I'm a programmer in javascript writing script");
function confirmEnding(string) {
let target = "ipt";
return (string.substr(-target.length) === target) ? true : false;
}
function mySearchResult() {
return ages.filter(confirmEnding);
}
mySearchResult();
you could check like this and return an array of the matched words using filter
I had a problem like this. I had a URL, I wanted to check if the link ends in an image format or other file format, having an array of images format. Here is what I did:
const imagesFormat = ['.jpg','.png','.svg']
const link = "https://res.cloudinary.com/***/content/file_padnar.pdf"
const isIncludes = imagesFormat.some(format => link.includes(format))
// false
You can check like this:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
var list = ["bad", "words", "include"]
var sentence = $("#comments_text").val()
$.each(list, function( index, value ) {
if (sentence.indexOf(value) > -1) {
console.log(value)
}
});
});
</script>
</head>
<body>
<input id="comments_text" value="This is a bad, with include test">
</body>
</html>
let obj = [{name : 'amit'},{name : 'arti'},{name : 'sumit'}];
let input = 'it';
Use filter :
obj.filter((n)=> n.name.trim().toLowerCase().includes(input.trim().toLowerCase()))
var str = "A for apple"
var subString = ["apple"]
console.log(str.includes(subString))

Categories