nodejs [] operator, avoid picking first char of array of strings - javascript

I have an array of strings that sometimes is an array that only contains one string.
when that is the case array[0] does not return the whole string but returns the first char in the string.
I can get around it with some if checking if length is > 1 but it is awful.
is there a safe [] operator or method that always return the whole string in position 0 of the array instead of the first char in the string?
This is an express input-based array in an html form.
I don't really have too much control over how it's generated.
i can't use a foreach as I have other parallel arrays from that form.

Before operating your var as an array, you should verify that it is an array.
In you case, i guess that when you get only a string the provider of your data return a string type and when there is more than one string it return an array of string.
So you need to verify the type returned by your data provider and then process with the right type.
if ( Array.isArray(yourVar) ) {
console.log('My var is an array');
} else {
console.log('My var is not an array');
}
You can also use typeof to check your var type, for example verify that your var is a string.

Related

String split method is returning empty string array

I am new to Javascript. I want to know why the string split method is returning an array of two empty strings when I use this method with a forwarding slash.
"/".split("/") // => ["", ""]
The string split function considers empty strings as acceptable outputs for splitting. So:
"a".split("a") == ["",""]; // is true, since
"a" == "" + "a" + ""; // is true; and more importantly,
["",""].join("a") == "a"; // is true
In short, the string split function has to give empty strings so that the .join() operator is the inverse of split.
Otherwise, if "/".split("/") gave [], then "/".split("/").join("/") would be "", which violates this inverseness.
If you want to actually get an empty array, you could do "/".split("/").filter(i=>i!=""), or just "/".split("/").filter(i=>i). Or some other variant.
According to MDN, it will divide the string into ordered sub strings.
It will consider space as well.

Javascript regex non greedy with global doesn't seems to be working

I was trying to get rid of empty attribute groups from the following string.
var str = '{"groups":[{"groupId":"03V5DCC","attributes":{}},{"groupId":"02VXTCB","attributes":{"registrationId":"550049390"}},{"groupId":"W3UV5SD","attributes":{}},],"status":{"code":200,"messageResource":"string-serverres-success"}}';
// tried with g and without g
console.log(str.replace(/\{"groupId":".*?","attributes":\{\}\},/g,''));
// Output: "{"groups":[],"status":{"code":200,"messageResource":"string-serverres-success"}}"
console.log(str.replace(/\{"groupId":".*?","attributes":\{\}\},/,''));
// Output: "{"groups":[{"groupId":"02VXTCB","attributes":{"registrationId":"550049390"}},{"groupId":"W3UV5SD","attributes":{}},],"status":{"code":200,"messageResource":"string-serverres-success"}}"
.as-console-wrapper {
max-height: 100% !important;
}
The one with global becomes greedy and removes groups even with attribute and the other one without g is just removing the first match.
Since the JSON is quite big in size(~10mb) parsing is not an option for me before reducing the string size.
The non-greedy .*? is in fact not greedy, but it will consume characters until whatever follows it does match. Thus if there's a group with non-empty attributes, that will not satisfy the match, so the .*? will continue to "eat" characters in the string until it finds a match.
As others have noted, don't do it this way. Parse the string as JSON and then operate on the data structure itself. If you need it as JSON afterwards, re-serialize it with JSON.stringify().
You can remove the properties as you are parsing if you use the optional reviver parameter of JSON.parse. It's a function that will run against each key-value pair and can modify or drop values as the parsing algorithm goes. So, you can watch for a key of attributes and check if the value is an empty object. If so, return undefined from the reviver and that key-value pair will be discarded. Otherwise, just proceed as normal:
var str = '{"groups":[{"groupId":"03V5DCC","attributes":{}},{"groupId":"02VXTCB","attributes":{"registrationId":"550049390"}},{"groupId":"W3UV5SD","attributes":{}}],"status":{"code":200,"messageResource":"string-serverres-success"}}';
var obj = JSON.parse(str, function (key, value) {
//if the key is `attribute` and the value is empty, then drop it
if (key === "attributes" && isEmpty(value))
return undefined;
//just return the value
return value;
}
)
//sample implementation of a check for empty objects
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
console.log(obj);

Parse incorrect JSON

I use JSON to send data to websocket. Sometimes websocket recive many messages as one, and event.data looks like:
{"message1":"message1"}{"message2":"message2"}
so i can't parse it with JSON.Parse. How to handle this problem?
Here's an example of an auto-recovering JSON parser, which you can use to parse concatenated jsons:
function *multiJson(str) {
while (str) {
try {
yield JSON.parse(str);
str = '';
} catch(e) {
var m = String(e).match(/position\s+(\d+)/);
yield JSON.parse(str.slice(0, m[1]));
str = str.slice(m[1]);
}
}
}
//
let test = '{"message1":"message1"}{"message2":{"nested":"hi}{there"}}"third"[4,5,6]';
for (let x of multiJson(test))
console.log(x)
Basically, if there's a syntax error at position n, it tries to parse out everything before n and what's after it.
If you cannot fix it on the sending side and it always looks like this, then you might try to fix it and replace '}{' with '}\n{', split on newlines and have an array of JSON strings.
var array = input.replace('}{', '}\n{').split('\n');
Note that if your input contains newlines then you have to use another character or string:
var array = input.replace('}{', '}==XXX=={').split('==XXX==');
but it relies on fact that you don't have '}{' anywhere else in the string, which may not be true.
A more correct way, but harder, would be to count { and } that are not inside of strings, and when you get the same number of } as the number of { then split the string there.
What you would have to do is go character by character and keep track of whether you are inside quotes or not, make every { increment a counter, } decrement a counter and split your input whenever your counter hits zero.
Another hacky way would be to try to split the string on every possible } and try to parse the substring as JSON and if it's valid then use it and remove from the input.
If you have any control over the API then I would strongly recommend that you have it fixed there. However if you don't the please proceed reading.
I assume that looking for "}" is not really an option since you could have nested objects and the } character might be inside a string and so on.
A quick and easy way would be to try parse the string starting with 1 character and adding characters one by one until the JSON parser does not fail. That is when you will have your first chunk of data parsed.
Move the offset to the end of the successfully parsed data and repeat.
Might not be an elegant solution or very efficient one but then again you have a non standard data format.

How are strings physically stored in Javascript

What I am looking for is how strings are physically treated in Javascript. Best example I can think of for what I mean is that in the Java api it describes the storage of strings as:
String str = "abc";" is equivalent to: "char data[] = {'a', 'b', 'c'};
To me this says it uses an array object and stores each character as its own object to be used/accessed later (I am usually wrong on these things!)...
How does Javascript do this?
Strings are String objects in JavaScript. The String object can use the [] notation to get character from a string ("abc"[0] returns 'a'). You can also use the String.prototype.charAt function to achieve the same result.
Side node: var a = 'abc' and var b = new String('abc') are not the same. The first case is called a primitive string and get converted to a String object by the JavaScript parser. This results in other data types, calling typeof(a) gives you string but typeof(b) gives you object.
Strings are stored in the same format in javascript as other languages stores.
Suppose var word = "test" than at word will be as an array of characters and the 't' will come at 0th position and so on.
The last iteration as taking 'word.length' will return undefined. In other languages, it returns as '\0'.

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

Categories

Resources