Why [,,].join(' ') length is one less than array length? - javascript

What is the reason behind the length of string produced by joining var arr = [,,], like so: var str = arr.join(' ') being one less than length of arr.
var literal_arr = [,,],
joined_literal_arr = literal_arr.join(' '),
constructor_arr = new Array(2),
joined_constructor_arr = new Array(2).join(' ');
console.log("Literal array notation length = ", literal_arr.length);
console.log("Joined literal array notation string length = ", joined_literal_arr.length);
console.log("Constructor array notation length = ", constructor_arr.length);
console.log("Joined constructor notation string length = ", joined_constructor_arr.length);

As per MDN docs :
If an element is undefined or null, it is converted to the empty string.
In your case, you are creating an array with a particular length without any value(it would be undefined). So while joining there will be length - 1 separators(since undefined already treated as an empty string) means length - 1 spaces(' ').

It is simple as .join will join array elements with separator provided as argument. It won’t append separator after the last element or prepend it before the first element. It will place separator between elements only.

Related

How Can I show the second array from string came from .split()

I have this string
a = "This is just an example";
If I used
split(" ",1)
it will print the first word as an array.
My question is how can I split just the second string as an array?
Use a limit of 2, then slice starting from the second element.
a = "This is just an example";
console.log(a.split(" ", 2).slice(1));
Or split the string with a limit of 2, then use an array literal containing just the second element.
a = "This is just an example";
console.log([a.split(" ", 2)[1]]);
A Better Approach would be to split on a space & that will give you an array of string, select the index you want & split it further
Note : ARRAY INDEX STARTS FROM 0 NOT ONE, SO IF YOU WANT THE SECOND STRING, YOU WILL HAVE TO USE THE INDEX 1, NOT 2
const a = "This is just an example";
const secondWordArr = a.split(' ')[1].split('');
// secondWordArr represents the array of characters of the seconds word
console.log(secondWordArr); // Output [ 'i', 's' ]
Explanation :
a.split(' ') // this splits the string into an array of strings/words
a.split(' ')[1] // Access the second string in the array of split strings/words
a.split(' ')[1].split('') // splits the second string from the array of strings/words into a separate array//

issue with substring indexing

Instructions for this kata:
In this Kata, we will check if a string contains consecutive letters as they appear in the English alphabet and if each letter occurs only once.
It seems that my code is indexing the strings differently per function call on this one. for example, on the first test "abcd", the starting index is shown as 0, which is correct, and on the second example, "himjlk", the
var subString = alphabet.substring(startIndex, length);
returns "g", instead of "h"
troubleshooting this section
var length = orderedString.length;
//startChar for string comparison
var startChar = orderedString.charAt(0);
//find index in aphabet of first character in orderedString.
var startIndex = alphabet.indexOf(startChar);
//create substring of alphabet with start index of orderedString and //orderedString.length
var subString = alphabet.substring(startIndex, length);
function solve(s) {
//alphabet string to check against
const alphabet = `abcdefghijklmnopqrstuvwxyz`;
//check s against alphabet
//empty array to order input string
var ordered = [];
//iterate through alphabet, checking against s
//and reorder input string to be alphabetized
for (var z in alphabet) {
var charToCheck = alphabet[z];
for (var i in s) {
if (charToCheck === s[i]) {
ordered.push(s[i]);
}
//break out of loop if lengths are the same
if (ordered.length === s.length) {
break;
}
}
if (ordered.length === s.length) {
break;
}
}
//join array back into string
var orderedString = ordered.join(``);
//length for future alphabet substring for comparison
var length = orderedString.length;
//startChar for string comparison
var startChar = orderedString.charAt(0);
//find index in aphabet of first character in orderedString.
var startIndex = alphabet.indexOf(startChar);
//create substring of alphabet with start index of orderedString and orderedString.length
var subString = alphabet.substring(startIndex, length);
//return if the two are a match
return subString == orderedString ? true : false;
}
console.log(solve("abdc")); //expected `true`
console.log(solve("himjlk")); // expected `true`
console.log(solve("abdc")); should provide the substring "abcd" and return true, which it does.
console.log(solve("himjlk")); should put together "hijklm" and return true, but instead gives me g based on index 6 of alphabet, not sure why it's doing this, should be index 7 "h" returns false based upon this error.
The problem is that you're using substring() instead of substr(). Though that might sound similar there's a difference.
With substring the second parameter doesn't determine the length as you might have expected. It's actually the index to stop.
That your function works as expected with the string abcd is pure coincidence since in this case the length from index 0 and the end index are the same.
function solve(s){
const alphabet = `abcdefghijklmnopqrstuvwxyz`;
var ordered = [];
for(var z in alphabet){
var charToCheck = alphabet[z];
for(var i in s){
if(charToCheck === s[i]){
ordered.push(s[i]);
}
if(ordered.length === s.length){ break; }
}
if(ordered.length === s.length){ break; }
}
var orderedString = ordered.join(``);
var length = orderedString.length;
var startChar = orderedString.charAt(0);
var startIndex = alphabet.indexOf(startChar);
var subString = alphabet.substr(startIndex, length);
return subString == orderedString ? true: false;
}
console.log(solve("himjlk"));
You approach is also correct. I am giving another solution using sort() and charCodeAt. Instead of getting the index and then breaking string into parts to compare just use includes()
function check(str){
let org = [...Array(26)].map((x,i) => String.fromCharCode(i + 97)).join('');
str = str.split('').sort((a, b) => a.charCodeAt(0) - b.charCodeAt(0)).join('');
return org.includes(str);
}
console.log(check("abdc"))//true
console.log(check("himjlk"));//true
console.log(check("himjlkp"));//false
Explanation:
Frist Line:
let org = [...Array(26)].map((x,i) => String.fromCharCode(i + 97)).join('');
is use to create string "abcd....xyz".
[...Array(26)] will create an array of 26(no of alphabets) undefined values.
map() is a function which takes a callback and the create an array based the values of previous. The first parameter of map() callback x is the value itself which will be undefined(because all the values in array are undefined).
i the second parameter will be the index of the element. Which will start from 0 upto 25.
String.fromCharCode is function which takes a character code(integer) and then convert it to string. For example character code for a is 97 so String.fromCharCode(97) will return "a". 98 for "b", 99 for "c" etc.
So after map() an array like ["a","b"....,"z"] will be generated.
-join() will convert that to string
Second Line:
str is given string. str.split('') will convert string to array. For example
if str is "abdc" it will return ["a","b","d","c"]
sort() is the array method which takes the callback. The two parameters are two values to be compared during sort(). a and b are two values.
charCodeAt acts in reverse as String.fromCharCode. For example "a".charCodeAt(0) will be return 97 for "b" it will 98 and so on.
a.charCodeAt(0) - b.charCodeAt(0) which is returned from sort() will sort array is ascending order. And join() will convert array to string.
So string "abdc" will become "abcd"
Third Line:
The third line is the main one. org is string "abcdefghijklmnopqrstuvwxyz". Now if any string is a substring of this string then it means its in alphabetical order. So we check the sorted str is includes in the string or not.
You can clean up the second line by
str = str.split('').sort().join('');
Because if no callback is passed to sort() it will sort in default order. Mean alphabetical order.

Regex matching comma delimited strings

Given any of the following strings, where operator and value are just placeholders:
"operator1(value)"
"operator1(value), operator2(value)"
"operator1(value), operator2(value), operator_n(value)"
I need to be able to match so i can get each operator and it's value as follows:
[[operator1, value]]
[[operator1, value], [operator2, value]]
[[operator1, value], [operator2, value], [operator_n, value]]
Please Note: There could be n number of operators (comma delimited) in the given string.
My current attempt will match on operator1(value) but nothing with multiple operators. See regex101 for the results.
/^(.*?)\((.*)\)$/
You should be able to do this with a single regex using the global flag.
var re= /(?:,\s*)?([^(]+?)\(([^)]+)\)/g;
var results = re.exec(str);
See the result at Regex 101: https://regex101.com/r/eC3uK3/2
Here's a pure regex answer to this question, this will work so long as your variables are always separated by a , and a space, should traverse through lines without much issue
https://regex101.com/r/eC3uK3/4
([^\(]*)(\([^, ]*\))(?:, )?(?:\n)?
Matches on:
operator1(value), operator2(value), operator_n(value),
operator1(value), operator2(value)
Explanation:
So, this sets up 2 capture groups and 2 non-capture groups.
The first capture group will match a value name until a parenthesis (by using a negated set and greedy). The second capture group will grab the parenthesis and the value name until the end of the parenthesis are found (note you can get rid of the parenthesis by escaping the outer set of parenthesis rather than the inner (Example here: https://regex101.com/r/eC3uK3/6). There's an optional ", " in a non capturing group, and an optional "\n" in another non-capturing group to handle any newline characters that you may happen across.
This should break your data out into:
'Operator1'
'(value)'
'operator2'
'(value)'
For as many as there are.
You can do this by first splitting then using a regular expression:
[
"operator1(value)",
"operator1(value), operator2(value)",
"operator1(value), operator2(value), operator_n(value)"
].forEach((str)=>{
var results = str
.split(/[,\s]+/) // split operations
.map(s=>s.match(/(\w+)\((\w+)\)/)) // extracts parts of the operations
.filter(Boolean) // ensure there's no error (in case of impure entries)
.map(s=>s.slice(1)); // make the desired result
console.log(results);
});
The following function "check" will achieve what you are looking for, if you want a string instead of an array of result, simply use the .toString() method on the array returned from the function.
function check(str) {
var myRe = /([^(,\s]*)\(([^)]*)\)/g;
var myArray;
var result = [];
while ((myArray = myRe.exec(str)) !== null) {
result.push(`[${myArray[1]}, ${myArray[2]}]`);
};
return result;
}
var check1 = check("operator1(value)");
console.log("check1", check1);
var check2 = check("operator1(value), operator2(value)");
console.log("check2", check2);
var check3 = check("operator1(value), operator2(value), operator_n(value)");
console.log("check3", check3);
This can also be done with a simple split and a for loop.
var data = "operator1(value), operator2(value), operator_n(value)",
ops = data.substring(0, data.length - 1), // Remove the last parenth from the string
arr = ops.split(/\(|\), /),
res = [], n, eN = arr.length;
for (n = 0; n < eN; n += 2) {
res.push([arr[n], arr[n + 1]]);
}
console.log(res);
The code creates a flattened array from a string, and then nests arrays of "operator"/"value" pairs to the result array. Works for older browsers too.

JavaScript split gives array size one instead of zero for empty string

I want to split a string by comma to get an array in Node.js.
exports.test = function(rq, rs){
var mailList = "sharan#test.com,pradeep#test.com";
var arrayList = mailList.split(",");
console.log(mailList + " array lenght " + arrayList.length );
mailList = "";
arrayList = mailList.split(",");
console.log(mailList + " array lenght " + arrayList.length );
mailList = "sharan#test.com,";
console.log(mailList + " array lenght " + arrayList.length );
mailList = ",";
console.log(mailList + " array lenght " + arrayList.length );
rs.send("test here ");
}
The console output is:
sharan#test.com,pradeep#test.com array lenght 2
array lenght 1
sharan#test.com, array lenght 1
, array lenght 1
Why does the JavaScript "".split() return an array with one element instead of an empty array?
The returned array contains a single empty string ([""]). It works this way because everything up until the first match (or end of string) is returned as the first element of the array. In the case of the empty string, this is an empty string.
If you think about how an implementation of the split algorithm might look like, this makes sense. Probably you start with an empty string containing the current element, and then you loop through the letters of the string adding them to the current element until you get to the end of the string or a separator. Then you push the current element onto the results array.
In the case where you have a zero length string, you start with an empty string for the current element. You directly reach the end, so you push the empty string to the results array an return it.
This is also how it is supposed to work. From the ECMAScript Language Specification:
If the this object is (or converts to) the empty String, the result depends on whether separator can match the empty String. If it can, the result array contains no elements. Otherwise, the result array contains one element, which is the empty String.
And from Mozilla:
When found, separator is removed from the string and the substrings are returned in an array. If separator is not found or is omitted, the array contains one element consisting of the entire string.
Note: When the string is empty, split() returns an array containing one empty string, rather than an empty array.
If you dislike the behavior, you can write your own version:
//Return an empty array if string is empty.
//Otherwise return the result of the ordinary split.
split2 = (separator) => this == "" ? [] : this.split(separator);
Everything before the first match is returned as the first element. Even if the String is Empty. It's not null
If you want split and return an 0 length Array, I recommand you to use the underscore.string module and the words method :
_str.words("", ",");
// => []
_str.words("Foo", ",");
// => [ 'Foo' ]
One way to do is to check whether the first value of the split array is empty or not
var arrayList = mailList.split(",");
if(arrayList[0] != ""){
arrayLength = arrayList.length;
}else{
arrayLength = 0;
}

Separate value from string using javascript

I have a string in which every value is between [] and it has a . at the end. How can I separate all values from the string?
This is the example string:
[value01][value02 ][value03 ]. [value04 ]
//want something like this
v1 = value01;
v2 = value02;
v3 = value03;
v4 = value04
The number of values is not constant. How can I get all values separately from this string?
Use regular expressions to specify multiple separators. Please check the following posts:
How do I split a string with multiple separators in javascript?
Split a string based on multiple delimiters
var str = "[value01][value02 ][value03 ]. [value04 ]"
var arr = str.split(/[\[\]\.\s]+/);
arr.shift(); arr.pop(); //discard the first and last "" elements
console.log( arr ); //output: ["value01", "value02", "value03", "value04"]
JS FIDDLE DEMO
How This Works
.split(/[\[\]\.\s]+/) splits the string at points where it finds one or more of the following characters: [] .. Now, since these characters are also found at the beginning and end of the string, .shift() discards the first element, and .pop() discards the last element, both of which are empty strings. However, your may want to use .filter() and your can replace lines 2 and 3 with:
var arr = str.split(/[\[\]\.\s]+/).filter(function(elem) { return elem.length > 0; });
Now you can use jQuery/JS to iterate through the values:
$.each( arr, function(i,v) {
console.log( v ); // outputs the i'th value;
});
And arr.length will give you the number of elements you have.
If you want to get the characters between "[" and "]" and the data is regular and always has the pattern:
'[chars][chars]...[chars]'
then you can get the chars using match to get sequences of characters that aren't "[" or "]":
var values = '[value01][value02 ][value03 ][value04 ]'.match(/[^\[\]]+/g)
which returns an array, so values is:
["value01", "value02 ", "value03 ", "value04 "]
Match is very widely supported, so no cross browser issues.
Here's a fiddle: http://jsfiddle.net/5xVLQ/
Regex patern: /(\w)+/ig
Matches all words using \w (alphanumeric combos). Whitespace, brackets, dots, square brackets are all non-matching, so they don't get returned.
What I do is create a object to hold results in key/value pairs such as v1:'value01'. You can iterate through this object, or you can access the values directly using objRes.v1
var str = '[value01][value02 ][value03 ]. [value04 ]';
var myRe = /(\w)+/ig;
var res;
var objRes = {};
var i=1;
while ( ( res = myRe.exec(str) ) != null )
{
objRes['v'+i] = res[0];
i++;
}
console.log(objRes);

Categories

Resources