JavaScript split() adding extra commas? - javascript

This is kind of confusing me. I don't know why this is happening, but it is breaking up my program I'm trying to create.
Basically, I have an var array = []. This array is called words. words has the contents of
var words = ["apple","banana","grape","orange","kiwi","cherry", "strawberry","plum"]
When I try to split it with:
var split = words.toString().split(" ");
it splits each word correctly ("apple,banana,etc").
However doing:
var split = words.toString().split("");
alert(split)
gives me "a,p,p,l,e,,,b,a,n,a,n,a,,,g,r,a,p,e,,, etc". Why is it doing this?
EDIT
I don't know why it adds "a,p,p,l,e,,,..." with extra commas per word.

words.toString()
gives
"apple,banana,grape,orange,kiwi,cherry,strawberry,plum"
because toString() on an array builds a readable representation with commas separating elements.
If you split that in characters with .split(""), you get
["a", "p", "p", "l", "e", ",", "b", ...
Notice that some of those elements are "," because you've split a string containing commas.
If you alert it, you're implicitly doing an extra toString() on that array, which gives
"a,p,p,l,e,,,b,a ...
If the purpose is to debug, don't use alert but console.log (you get access to the console with F12 on most browsers).
If your goal is to get an array with all the letters of your words, you may use
var letters = [].concat.apply([], words.map(function(v){ return v.split('') }));

When you use .toString() on a array it returns a string with all the values separated by commas.
When you use .split(" "). It doesn't split anything because there are no spaces in your string. It returns a array with one single value.
When you use .split("") it splits every character. This creates a array with all characters including the commas .toString() added. So when you do:
var split = words.toString().split("");
It gives you this array: ["a","p","p","l","e",",""b", etc
Calling .toString() on this array returns your result.

The first split(words.toString().split(" ")) is trying to split the result of converting words.toString() which is apple,banana,grape,orange,kiwi,cherry,strawberry,plum with empty spaces, because it doesn't find any empty spaces it return an array with the entire string.
The second split, var split = words.toString().split(""); you are not passing anything to split method because in javascript " " and "" are not the same. so when you pass "" to split method javascript assumes that you want to split every single character on the string. basically is the default behaviour of the method when you don't pass anything into it.

Related

Empty value if regex match not found JavaScript

I'm attempting to extract any text characters at the beginning, and the following two numbers of a string. If the string starts with a number, I'd like to get an empty string value instead so the resulting array still contains 3 values.
String:
'M2.55X.45'
Code:
'M2.55X.45'.match(/(^[a-zA-Z]+)|((\.)?\d+[\/\d. ]*|\d)/g)
Expected:
["M", "2.55", ".45"]
Actual (correct):
["M", "2.55", ".45"]
String:
'2.55X.45'
Code:
'2.55X.45'.match(/(^[a-zA-Z]+)|((\.)?\d+[\/\d. ]*|\d)/g)
Expected:
["", "2.55", ".45"]
Actual:
["2.55", ".45"]
Use /^([a-zA-Z]?)(\d*(?:\.\d+)?)[a-zA-Z](\d*(?:\.\d+)?)$/.exec("2.55X.45") instead. This returns an array where the 1st element is the entire match, so you must access groups 1-indexed, for example, match[1] for the 1st value. You can try this out here.
Your current regex uses an alternate clause (|), which creates different types of grouping depending on which alternate is matched.
Here's an example (cleaned up a bit) that creates explicit groups and makes the individual groups optional.
const regex = /^([a-zA-Z]*)?(\d*(?:\.\d+)?)([a-zA-Z]+)(\d*(?:\.\d+)?)$/
console.log(regex.exec("2.55X.45"))
console.log(regex.exec("M2.55X.45"))
Note that I've removed the g flag, so the regex's state isn't preserved.
I've also used exec instead of match to not discard capture groups.
You can try this pattern
(\D*)(\d+(?:\.\d+))\D+(\.\d+)
let finder = (str) => {
return (str.match(/^(\D*)(\d+(?:\.\d+))\D+(\.\d+)/) || []).slice(1)
}
console.log(finder('M2.55X.45'))
console.log(finder("2.55X.45"))

Regular Expression to get the last word from TitleCase, camelCase

I'm trying to split a TitleCase (or camelCase) string into precisely two parts using javascript. I know I can split it into multiple parts by using the lookahead:
"StringToSplit".split(/(?=[A-Z])/);
And it will make an array ['String', 'To', 'Split']
But what I need is to break it into precisely TWO parts, to produce an array like this:
['StringTo', 'Split']
Where the second element is always the last word in the TitleCase, and the first element is everything else that precedes it.
Is this what you are looking for ?
"StringToSplit".split(/(?=[A-Z][a-z]+$)/); // ["StringTo", "Split"]
Improved based on lolol answer :
"StringToSplit".split(/(?=[A-Z][^A-Z]+$)/); // ["StringTo", "Split"]
Use it like this:
s = "StringToSplit";
last = s.replace(/^.*?([A-Z][a-z]+)(?=$)/, '$1'); // Split
first = s.replace(last, ''); // StringTo
tok = [first, last]; // ["StringTo", "Split"]
You could use
(function(){
return [this.slice(0,this.length-1).join(''), this[this.length-1]];
}).call("StringToSplit".split(/(?=[A-Z])/));
//=> ["StringTo", "Split"]
In [other] words:
create the Array using split from a String
join a slice of that Array without the last element of that
Array
add that and the last element to a final Array

What are elegant ways to pair characters in a string?

For example, if the initial string s is "0123456789", desired output would be an array ["01", "23", "45", "67", "89"].
Looking for elegant solutions in JavaScript.
What I was thinking (very non-elegantly) is to iterate through the string by splitting on the empty string and using the Array.forEach method, and insert a delimeter after every two characters, then split by that delimeter. This is not a good solution, but it's my starting point.
Edit: A RegExp solution has been posted. I'd love to see if there are any other approaches.
How about:
var array = ("0123456789").match(/\w{1,2}/g);
Here we use .match() on your string to match any two or single ({1,2}) word characters (\w) and return an array of the results.
Regarding your edit for a non-regex solution; you could do a far less elegant function like this:
String.prototype.getPairs = function()
{
var pairs = [];
for(var i = 0; i < this.length; i += 2)
{
pairs[pairs.length] = this.substr(i, 2);
}
return pairs;
}
var array = ("01234567890").getPairs();
If you want to use split (and why not), you could do the following:
s.split(/([^][^])/).filter(function(x){return x})
Which splits using two consecutive characters as a delimiter (but because they're in a capture group, they're also part of split's result. Filtering that with the identity function serves to eliminate the empty strings (between the "delimiters"). Note that in the case of an odd number of characters, the last character will be output as a split, not a delimiter, but it doesn't matter since it will still test truthy.
([^] is how you spell . in javascript if you really want to match any character. I had to look that up.)

String split returns an array with more elements than expected (empty elements)

I don't understand this behaviour:
var string = 'a,b,c,d,e:10.';
var array = string.split ('.');
I expect this:
console.log (array); // ['a,b,c,d,e:10']
console.log (array.length); // 1
but I get this:
console.log (array); // ['a,b,c,d,e:10', '']
console.log (array.length); // 2
Why two elements are returned instead of one? How does split work?
Is there another way to do this?
You could add a filter to exclude the empty string.
var string = 'a,b,c,d,e:10.';
var array = string.split ('.').filter(function(el) {return el.length != 0});
A slightly easier version of #xdazz version for excluding empty strings (using ES6 arrow function):
var array = string.split('.').filter(x => x);
This is the correct and expected behavior. Given that you've included the separator in the string, the split function (simplified) takes the part to the left of the separator ("a,b,c,d,e:10") as the first element and the part to the rest of the separator (an empty string) as the second element.
If you're really curious about how split() works, you can check out pages 148 and 149 of the ECMA spec (ECMA 262) at http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Use String.split() method with Array.filter() method.
var string = 'a,b,c,d,e:10.';
var array = string.split ('.').filter(item => item);
console.log(array); // [a,b,c,d,e:10]
console.log (array.length); // 1
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/split
trim the trailing period first
'a,b,c,d,e:10.'.replace(/\.$/g,''); // gives "a,b,c,d,e:10"
then split the string
var array = 'a,b,c,d,e:10.'.replace(/\.$/g,'').split('.');
console.log (array.length); // 1
That's because the string ends with the . character - the second item of the array is empty.
If the string won't contain . at all, you will have the desired one item array.
The split() method works like this as far as I can explain in simple words:
Look for the given string to split by in the given string. If not found, return one item array with the whole string.
If found, iterate over the given string taking the characters between each two occurrences of the string to split by.
In case the given string starts with the string to split by, the first item of the result array will be empty.
In case the given string ends with the string to split by, the last item of the result array will be empty.
It's explained more technically here, it's pretty much the same for all browsers.
According to MDN web docs:
Note: When the string is empty, split() returns an array containing
one empty string, rather than an empty array. If the string and
separator are both empty strings, an empty array is returned.
const myString = '';
const splits = myString.split();
console.log(splits);
// ↪ [""]
Well, split does what it is made to do, it splits your string. Just that the second part of the split is empty.
Because your string is composed of 2 part :
1 : a,b,c,d,e:10
2 : empty
If you try without the dot at the end :
var string = 'a,b,c:10';
var array = string.split ('.');
output is :
["a,b,c:10"]
You have a string with one "." in it and when you use string.split('.') you receive array containing first element with the string content before "." character and the second element with the content of the string after the "." - which is in this case empty string.
So, this behavior is normal. What did you want to achieve by using this string.split?
try this
javascript gives two arrays by split function, then
var Val = "abc#gmail.com";
var mail = Val.split('#');
if(mail[0] && mail[1]) { alert('valid'); }
else { alert('Enter valid email id'); valid=0; }
if both array contains length greater than 0 then condition will true

javascript spilt to get part of the word

I tried use javascript spilt to get part of the word : new from What#a_new%20day
I tried code like this:
<script>
var word="What#a_new%20day";
var newword = word.split("%20", 1).split("_", 2);
alert(newword);
</script>
But caused:
Uncaught TypeError: Object What#a_new has no method 'split'
Maybe there have more wiser way to get the word which I need. So can anyone help me? Thanks.
split returns an array, so the second split is trying to operate on the array returned by the first, rather than a string, which causes a TypeError. You'll also want to add the correct index after the second call to split, or newword will also be an array, not the String you're expecting. Change it to:
var newword = word.split("%20", 1)[0].split("_", 2)[1];
This splits word, then splits the string at index 0 of the resulting array, and assigns the value of the string at index 1 of the new array to newword.
Regex to the rescue
var word="What#a_new%20day";
var newword = word.match(/_(.+)%/)[1];
alert(newword);
this returns the first ([1]) captured group ((...)) in the regex (_(.+)%) which is _ followed by any character (.) one or more times (+) followed by %.
the result of a split is an array, not a string. so what you need to do is
<script>
var word="What#a_new%20day";
var newword = word.split("%20", 1)[0].split("_", 2);
alert(newword);
</script>
notice the [0]
split returns an array:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split
word.split("%20", 1);
gives an array so you cannot do :
(result from above).split("_", 2);
If split is what your after, go for it, but performance wise, it would be better to do something like this:
var word="What#a_new%20day";
var newword = word.substr(word.indexOf('new'),3)
alert(newword);
Live example: http://jsfiddle.net/qJ8wM/
Split searches for all instances of %20 in the text, whereas indexOf finds the first instance, and substr is fairly cheap performance wise as well.
JsPerf stats on split vs substring (a general case): http://jsperf.com/split-vs-substring

Categories

Resources