Parsing Data in Silverlight [duplicate] - vb.net
Where could I find some JavaScript code to parse CSV data?
You can use the CSVToArray() function mentioned in this blog entry.
<script type="text/javascript">
// ref: http://stackoverflow.com/a/1293163/2343
// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.
function CSVToArray( strData, strDelimiter ){
// Check to see if the delimiter is defined. If not,
// then default to comma.
strDelimiter = (strDelimiter || ",");
// Create a regular expression to parse the CSV values.
var objPattern = new RegExp(
(
// Delimiters.
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
// Quoted fields.
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
// Standard fields.
"([^\"\\" + strDelimiter + "\\r\\n]*))"
),
"gi"
);
// Create an array to hold our data. Give the array
// a default empty first row.
var arrData = [[]];
// Create an array to hold our individual pattern
// matching groups.
var arrMatches = null;
// Keep looping over the regular expression matches
// until we can no longer find a match.
while (arrMatches = objPattern.exec( strData )){
// Get the delimiter that was found.
var strMatchedDelimiter = arrMatches[ 1 ];
// Check to see if the given delimiter has a length
// (is not the start of string) and if it matches
// field delimiter. If id does not, then we know
// that this delimiter is a row delimiter.
if (
strMatchedDelimiter.length &&
strMatchedDelimiter !== strDelimiter
){
// Since we have reached a new row of data,
// add an empty row to our data array.
arrData.push( [] );
}
var strMatchedValue;
// Now that we have our delimiter out of the way,
// let's check to see which kind of value we
// captured (quoted or unquoted).
if (arrMatches[ 2 ]){
// We found a quoted value. When we capture
// this value, unescape any double quotes.
strMatchedValue = arrMatches[ 2 ].replace(
new RegExp( "\"\"", "g" ),
"\""
);
} else {
// We found a non-quoted value.
strMatchedValue = arrMatches[ 3 ];
}
// Now that we have our value string, let's add
// it to the data array.
arrData[ arrData.length - 1 ].push( strMatchedValue );
}
// Return the parsed data.
return( arrData );
}
</script>
jQuery-CSV
It's a jQuery plugin designed to work as an end-to-end solution for parsing CSV into JavaScript data. It handles every single edge case presented in RFC 4180, as well as some that pop up for Excel/Google spreadsheet exports (i.e., mostly involving null values) that the specification is missing.
Example:
track,artist,album,year
Dangerous,'Busta Rhymes','When Disaster Strikes',1997
// Calling this
music = $.csv.toArrays(csv)
// Outputs...
[
["track", "artist", "album", "year"],
["Dangerous", "Busta Rhymes", "When Disaster Strikes", "1997"]
]
console.log(music[1][2]) // Outputs: 'When Disaster Strikes'
Update:
Oh yeah, I should also probably mention that it's completely configurable.
music = $.csv.toArrays(csv, {
delimiter: "'", // Sets a custom value delimiter character
separator: ';', // Sets a custom field separator character
});
Update 2:
It now works with jQuery on Node.js too. So you have the option of doing either client-side or server-side parsing with the same library.
Update 3:
Since the Google Code shutdown, jquery-csv has been migrated to GitHub.
Disclaimer: I am also the author of jQuery-CSV.
Here's an extremely simple CSV parser that handles quoted fields with commas, new lines, and escaped double quotation marks. There's no splitting or regular expression. It scans the input string 1-2 characters at a time and builds an array.
Test it at http://jsfiddle.net/vHKYH/.
function parseCSV(str) {
var arr = [];
var quote = false; // 'true' means we're inside a quoted field
// Iterate over each character, keep track of current row and column (of the returned array)
for (var row = 0, col = 0, c = 0; c < str.length; c++) {
var cc = str[c], nc = str[c+1]; // Current character, next character
arr[row] = arr[row] || []; // Create a new row if necessary
arr[row][col] = arr[row][col] || ''; // Create a new column (start with empty string) if necessary
// If the current character is a quotation mark, and we're inside a
// quoted field, and the next character is also a quotation mark,
// add a quotation mark to the current column and skip the next character
if (cc == '"' && quote && nc == '"') { arr[row][col] += cc; ++c; continue; }
// If it's just one quotation mark, begin/end quoted field
if (cc == '"') { quote = !quote; continue; }
// If it's a comma and we're not in a quoted field, move on to the next column
if (cc == ',' && !quote) { ++col; continue; }
// If it's a newline (CRLF) and we're not in a quoted field, skip the next character
// and move on to the next row and move to column 0 of that new row
if (cc == '\r' && nc == '\n' && !quote) { ++row; col = 0; ++c; continue; }
// If it's a newline (LF or CR) and we're not in a quoted field,
// move on to the next row and move to column 0 of that new row
if (cc == '\n' && !quote) { ++row; col = 0; continue; }
if (cc == '\r' && !quote) { ++row; col = 0; continue; }
// Otherwise, append the current character to the current column
arr[row][col] += cc;
}
return arr;
}
I have an implementation as part of a spreadsheet project.
This code is not yet tested thoroughly, but anyone is welcome to use it.
As some of the answers noted though, your implementation can be much simpler if you actually have DSV or TSV file, as they disallow the use of the record and field separators in the values. CSV, on the other hand, can actually have commas and newlines inside a field, which breaks most regular expression and split-based approaches.
var CSV = {
parse: function(csv, reviver) {
reviver = reviver || function(r, c, v) { return v; };
var chars = csv.split(''), c = 0, cc = chars.length, start, end, table = [], row;
while (c < cc) {
table.push(row = []);
while (c < cc && '\r' !== chars[c] && '\n' !== chars[c]) {
start = end = c;
if ('"' === chars[c]){
start = end = ++c;
while (c < cc) {
if ('"' === chars[c]) {
if ('"' !== chars[c+1]) {
break;
}
else {
chars[++c] = ''; // unescape ""
}
}
end = ++c;
}
if ('"' === chars[c]) {
++c;
}
while (c < cc && '\r' !== chars[c] && '\n' !== chars[c] && ',' !== chars[c]) {
++c;
}
} else {
while (c < cc && '\r' !== chars[c] && '\n' !== chars[c] && ',' !== chars[c]) {
end = ++c;
}
}
row.push(reviver(table.length-1, row.length, chars.slice(start, end).join('')));
if (',' === chars[c]) {
++c;
}
}
if ('\r' === chars[c]) {
++c;
}
if ('\n' === chars[c]) {
++c;
}
}
return table;
},
stringify: function(table, replacer) {
replacer = replacer || function(r, c, v) { return v; };
var csv = '', c, cc, r, rr = table.length, cell;
for (r = 0; r < rr; ++r) {
if (r) {
csv += '\r\n';
}
for (c = 0, cc = table[r].length; c < cc; ++c) {
if (c) {
csv += ',';
}
cell = replacer(r, c, table[r][c]);
if (/[,\r\n"]/.test(cell)) {
cell = '"' + cell.replace(/"/g, '""') + '"';
}
csv += (cell || 0 === cell) ? cell : '';
}
}
return csv;
}
};
csvToArray v1.3
A compact (645 bytes), but compliant function to convert a CSV string into a 2D array, conforming to the RFC4180 standard.
https://code.google.com/archive/p/csv-to-array/downloads
Common Usage: jQuery
$.ajax({
url: "test.csv",
dataType: 'text',
cache: false
}).done(function(csvAsString){
csvAsArray=csvAsString.csvToArray();
});
Common usage: JavaScript
csvAsArray = csvAsString.csvToArray();
Override field separator
csvAsArray = csvAsString.csvToArray("|");
Override record separator
csvAsArray = csvAsString.csvToArray("", "#");
Override Skip Header
csvAsArray = csvAsString.csvToArray("", "", 1);
Override all
csvAsArray = csvAsString.csvToArray("|", "#", 1);
Here's my PEG(.js) grammar that seems to do ok at RFC 4180 (i.e. it handles the examples at http://en.wikipedia.org/wiki/Comma-separated_values):
start
= [\n\r]* first:line rest:([\n\r]+ data:line { return data; })* [\n\r]* { rest.unshift(first); return rest; }
line
= first:field rest:("," text:field { return text; })*
& { return !!first || rest.length; } // ignore blank lines
{ rest.unshift(first); return rest; }
field
= '"' text:char* '"' { return text.join(''); }
/ text:[^\n\r,]* { return text.join(''); }
char
= '"' '"' { return '"'; }
/ [^"]
Try it out at http://jsfiddle.net/knvzk/10 or http://pegjs.majda.cz/online. Download the generated parser at https://gist.github.com/3362830.
Here's another solution. This uses:
a coarse global regular expression for splitting the CSV string (which includes surrounding quotes and trailing commas)
fine-grained regular expression for cleaning up the surrounding quotes and trailing commas
also, has type correction differentiating strings, numbers, boolean values and null values
For the following input string:
"This is\, a value",Hello,4,-123,3.1415,'This is also\, possible',true,
The code outputs:
[
"This is, a value",
"Hello",
4,
-123,
3.1415,
"This is also, possible",
true,
null
]
Here's my implementation of parseCSVLine() in a runnable code snippet:
function parseCSVLine(text) {
return text.match( /\s*(\"[^"]*\"|'[^']*'|[^,]*)\s*(,|$)/g ).map( function (text) {
let m;
if (m = text.match(/^\s*,?$/)) return null; // null value
if (m = text.match(/^\s*\"([^"]*)\"\s*,?$/)) return m[1]; // Double Quoted Text
if (m = text.match(/^\s*'([^']*)'\s*,?$/)) return m[1]; // Single Quoted Text
if (m = text.match(/^\s*(true|false)\s*,?$/)) return m[1] === "true"; // Boolean
if (m = text.match(/^\s*((?:\+|\-)?\d+)\s*,?$/)) return parseInt(m[1]); // Integer Number
if (m = text.match(/^\s*((?:\+|\-)?\d*\.\d*)\s*,?$/)) return parseFloat(m[1]); // Floating Number
if (m = text.match(/^\s*(.*?)\s*,?$/)) return m[1]; // Unquoted Text
return text;
} );
}
let data = `"This is\, a value",Hello,4,-123,3.1415,'This is also\, possible',true,`;
let obj = parseCSVLine(data);
console.log( JSON.stringify( obj, undefined, 2 ) );
Here's my simple vanilla JavaScript code:
let a = 'one,two,"three, but with a comma",four,"five, with ""quotes"" in it.."'
console.log(splitQuotes(a))
function splitQuotes(line) {
if(line.indexOf('"') < 0)
return line.split(',')
let result = [], cell = '', quote = false;
for(let i = 0; i < line.length; i++) {
char = line[i]
if(char == '"' && line[i+1] == '"') {
cell += char
i++
} else if(char == '"') {
quote = !quote;
} else if(!quote && char == ',') {
result.push(cell)
cell = ''
} else {
cell += char
}
if ( i == line.length-1 && cell) {
result.push(cell)
}
}
return result
}
I'm not sure why I couldn't get Kirtan's example to work for me. It seemed to be failing on empty fields or maybe fields with trailing commas...
This one seems to handle both.
I did not write the parser code, just a wrapper around the parser function to make this work for a file. See attribution.
var Strings = {
/**
* Wrapped CSV line parser
* #param s String delimited CSV string
* #param sep Separator override
* #attribution: http://www.greywyvern.com/?post=258 (comments closed on blog :( )
*/
parseCSV : function(s,sep) {
// http://stackoverflow.com/questions/1155678/javascript-string-newline-character
var universalNewline = /\r\n|\r|\n/g;
var a = s.split(universalNewline);
for(var i in a){
for (var f = a[i].split(sep = sep || ","), x = f.length - 1, tl; x >= 0; x--) {
if (f[x].replace(/"\s+$/, '"').charAt(f[x].length - 1) == '"') {
if ((tl = f[x].replace(/^\s+"/, '"')).length > 1 && tl.charAt(0) == '"') {
f[x] = f[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
} else if (x) {
f.splice(x - 1, 2, [f[x - 1], f[x]].join(sep));
} else f = f.shift().split(sep).concat(f);
} else f[x].replace(/""/g, '"');
} a[i] = f;
}
return a;
}
}
Regular expressions to the rescue! These few lines of code handle properly quoted fields with embedded commas, quotes, and newlines based on the RFC 4180 standard.
function parseCsv(data, fieldSep, newLine) {
fieldSep = fieldSep || ',';
newLine = newLine || '\n';
var nSep = '\x1D';
var qSep = '\x1E';
var cSep = '\x1F';
var nSepRe = new RegExp(nSep, 'g');
var qSepRe = new RegExp(qSep, 'g');
var cSepRe = new RegExp(cSep, 'g');
var fieldRe = new RegExp('(?<=(^|[' + fieldSep + '\\n]))"(|[\\s\\S]+?(?<![^"]"))"(?=($|[' + fieldSep + '\\n]))', 'g');
var grid = [];
data.replace(/\r/g, '').replace(/\n+$/, '').replace(fieldRe, function(match, p1, p2) {
return p2.replace(/\n/g, nSep).replace(/""/g, qSep).replace(/,/g, cSep);
}).split(/\n/).forEach(function(line) {
var row = line.split(fieldSep).map(function(cell) {
return cell.replace(nSepRe, newLine).replace(qSepRe, '"').replace(cSepRe, ',');
});
grid.push(row);
});
return grid;
}
const csv = 'A1,B1,C1\n"A ""2""","B, 2","C\n2"';
const separator = ','; // field separator, default: ','
const newline = ' <br /> '; // newline representation in case a field contains newlines, default: '\n'
var grid = parseCsv(csv, separator, newline);
// expected: [ [ 'A1', 'B1', 'C1' ], [ 'A "2"', 'B, 2', 'C <br /> 2' ] ]
You don't need a parser-generator such as lex/yacc. The regular expression handles RFC 4180 properly thanks to positive lookbehind, negative lookbehind, and positive lookahead.
Clone/download code at https://github.com/peterthoeny/parse-csv-js
Just throwing this out there.. I recently ran into the need to parse CSV columns with Javascript, and I opted for my own simple solution. It works for my needs, and may help someone else.
const csvString = '"Some text, some text",,"",true,false,"more text","more,text, more, text ",true';
const parseCSV = text => {
const lines = text.split('\n');
const output = [];
lines.forEach(line => {
line = line.trim();
if (line.length === 0) return;
const skipIndexes = {};
const columns = line.split(',');
output.push(columns.reduce((result, item, index) => {
if (skipIndexes[index]) return result;
if (item.startsWith('"') && !item.endsWith('"')) {
while (!columns[index + 1].endsWith('"')) {
index++;
item += `,${columns[index]}`;
skipIndexes[index] = true;
}
index++;
skipIndexes[index] = true;
item += `,${columns[index]}`;
}
result.push(item);
return result;
}, []));
});
return output;
};
console.log(parseCSV(csvString));
Personally I like to use deno std library since most modules are officially compatible with the browser
The problem is that the std is in typescript but official solution might happen in the future https://github.com/denoland/deno_std/issues/641 https://github.com/denoland/dotland/issues/1728
For now there is an actively maintained on the fly transpiler https://bundle.deno.dev/
so you can use it simply like this
<script type="module">
import { parse } from "https://bundle.deno.dev/https://deno.land/std#0.126.0/encoding/csv.ts"
console.log(await parse("a,b,c\n1,2,3"))
</script>
I have constructed this JavaScript script to parse a CSV in string to array object. I find it better to break down the whole CSV into lines, fields and process them accordingly. I think that it will make it easy for you to change the code to suit your need.
//
//
// CSV to object
//
//
const new_line_char = '\n';
const field_separator_char = ',';
function parse_csv(csv_str) {
var result = [];
let line_end_index_moved = false;
let line_start_index = 0;
let line_end_index = 0;
let csr_index = 0;
let cursor_val = csv_str[csr_index];
let found_new_line_char = get_new_line_char(csv_str);
let in_quote = false;
// Handle \r\n
if (found_new_line_char == '\r\n') {
csv_str = csv_str.split(found_new_line_char).join(new_line_char);
}
// Handle the last character is not \n
if (csv_str[csv_str.length - 1] !== new_line_char) {
csv_str += new_line_char;
}
while (csr_index < csv_str.length) {
if (cursor_val === '"') {
in_quote = !in_quote;
} else if (cursor_val === new_line_char) {
if (in_quote === false) {
if (line_end_index_moved && (line_start_index <= line_end_index)) {
result.push(parse_csv_line(csv_str.substring(line_start_index, line_end_index)));
line_start_index = csr_index + 1;
} // Else: just ignore line_end_index has not moved or line has not been sliced for parsing the line
} // Else: just ignore because we are in a quote
}
csr_index++;
cursor_val = csv_str[csr_index];
line_end_index = csr_index;
line_end_index_moved = true;
}
// Handle \r\n
if (found_new_line_char == '\r\n') {
let new_result = [];
let curr_row;
for (var i = 0; i < result.length; i++) {
curr_row = [];
for (var j = 0; j < result[i].length; j++) {
curr_row.push(result[i][j].split(new_line_char).join('\r\n'));
}
new_result.push(curr_row);
}
result = new_result;
}
return result;
}
function parse_csv_line(csv_line_str) {
var result = [];
//let field_end_index_moved = false;
let field_start_index = 0;
let field_end_index = 0;
let csr_index = 0;
let cursor_val = csv_line_str[csr_index];
let in_quote = false;
// Pretend that the last char is the separator_char to complete the loop
csv_line_str += field_separator_char;
while (csr_index < csv_line_str.length) {
if (cursor_val === '"') {
in_quote = !in_quote;
} else if (cursor_val === field_separator_char) {
if (in_quote === false) {
if (field_start_index <= field_end_index) {
result.push(parse_csv_field(csv_line_str.substring(field_start_index, field_end_index)));
field_start_index = csr_index + 1;
} // Else: just ignore field_end_index has not moved or field has not been sliced for parsing the field
} // Else: just ignore because we are in quote
}
csr_index++;
cursor_val = csv_line_str[csr_index];
field_end_index = csr_index;
field_end_index_moved = true;
}
return result;
}
function parse_csv_field(csv_field_str) {
with_quote = (csv_field_str[0] === '"');
if (with_quote) {
csv_field_str = csv_field_str.substring(1, csv_field_str.length - 1); // remove the start and end quotes
csv_field_str = csv_field_str.split('""').join('"'); // handle double quotes
}
return csv_field_str;
}
// Initial method: check the first newline character only
function get_new_line_char(csv_str) {
if (csv_str.indexOf('\r\n') > -1) {
return '\r\n';
} else {
return '\n'
}
}
Just use .split(','):
var str = "How are you doing today?";
var n = str.split(" ");
Related
VSCode API: registerCompletionItemProvider doesn't work with "#" trigger symbol
I am trying to use registerCompletionItemProviderto add autocompletion inside of JSDoc comments, but my provider doesn't work on the "#" trigger symbol, it is strange, but with other symbols, like "|" or "!" it works fine. I tried to check it with the VSCode debugger but it shows that my provideCompletionItems function isn't even called on the "#" trigger symbol. That's how it looks like with the "#" symbol That's how it looks like with the "|" symbol or any other symbols My extension.ts file export function activate(context: ExtensionContext) { context.subscriptions.push( languages.registerCompletionItemProvider(SUPPORTED_LANGUAGES, { provideCompletionItems, }, "#"); ); } My provideCompletionItems const provideCompletionItems = ( doc: TextDocument, pos: Position ) => { let keys = Object.keys(JSDocElements); let completions = keys.map(key => { // #ts-ignore let e = JSDocElements[key]; let r = new CompletionItem(key + " "); r.documentation = e.desc; r.kind = CompletionItemKind.Snippet; return r; }); const txt = doc.getText(); const matcher = /\/\*\*[^\*](?:\r|\n|.)*?\*\//g; let match = matcher.exec(txt); let p = doc.offsetAt(pos); while (match) { if (match.index > p) { match = null; break; } if (match.index < p && match.index + match[0].length > p) { break; } match = matcher.exec(txt); } if (!match) return []; return completions; };
ML Kit Barcode Scanner (used in reactnative-camera) cut displayValue after U+0000 / NULL
I am trying to scan ECC Data Matrix code with binary content, but if there is a NULL byte I can only get the string up to there. Unfortunately, I have no control over these matrix codes, as I have to scan the codes provided. Does somebody has any idea? Is it possibly to convert the rawData? It would be enough if I received the content as a hex value. The rawData is allready hex, but not as expected, maybe it is also corrupt or in an unknown coding. Does somebody know encoding of rawdata? see https://developers.google.com/ml-kit/reference/ios/mlkitbarcodescanning/api/reference/Classes/MLKBarcode#rawdata
I found a solution for me: Here my Code for React-Native: import {DataMatrixDecodedBitStreamParser, ZXingStringEncoding} from "#zxing/library"; const bin2hex = (s)=> { // discuss at: https://locutus.io/php/bin2hex/ // original by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman) // bugfixed by: Linuxworld // improved by: ntoniazzi (https://locutus.io/php/bin2hex:361#comment_177616) // example 1: bin2hex('Kev') // returns 1: '4b6576' // example 2: bin2hex(String.fromCharCode(0x00)) // returns 2: '00' let i; let l; let o = ''; let n; s += ''; for (i = 0, l = s.length; i < l; i++) { n = s.charCodeAt(i) .toString(16); o += n.length < 2 ? '0' + n : n; } return o; } const hex2bin = (s)=> { // discuss at: https://locutus.io/php/hex2bin/ // original by: Dumitru Uzun (https://duzun.me) // example 1: hex2bin('44696d61') // returns 1: 'Dima' // example 2: hex2bin('00') // returns 2: '\x00' // example 3: hex2bin('2f1q') // returns 3: false const ret = [] let i = 0 let l s += '' for (l = s.length; i < l; i += 2) { const c = parseInt(s.substr(i, 1), 16); const k = parseInt(s.substr(i + 1, 1), 16); if (isNaN(c) || isNaN(k)) return false; ret.push((c << 4) | k); } return String.fromCharCode.apply(String, ret); } const fromHexString = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); const matrixcodeRAW2HEX = raw_hex => { let data = fromHexString(raw_hex); try { global.Buffer = global.Buffer || require('buffer').Buffer; ZXingStringEncoding.customDecoder = (stringContent, encodingName) => { let encodingName2 = encodingName; if(encodingName.toLowerCase()=="iso-8859-1"){ encodingName2="latin1"; } return new Buffer(stringContent).toString(encodingName2); } ZXingStringEncoding.customEncoder = (stringContent, encodingName) => { let encodingName2 = encodingName; if(encodingName.toLowerCase()=="iso-8859-1"){ encodingName2="latin1"; } return new Buffer(stringContent).toString(encodingName2); }; let newData = DataMatrixDecodedBitStreamParser.decode(data); return bin2hex(newData.getText()); }catch (e) { console.log(e); } } My function will return the original data as hex, so there is no problem with NUL, but you can also use hex2bin to get it as a Text if necessary. I´m using the zxing polyfill for JS => https://github.com/zxing-js/library, cause JS does not Cut String like Objective C do. I found out in Objective C NUL always will cut a string, so there is no solution yet.
Validating a non-empty String in Lo-Dash [duplicate]
Is there a string.Empty in JavaScript, or is it just a case of checking for ""?
Empty string, undefined, null, ... To check for a truthy value: if (strValue) { // strValue was non-empty string, true, 42, Infinity, [], ... } To check for a falsy value: if (!strValue) { // strValue was empty string, false, 0, null, undefined, ... } Empty string (only!) To check for exactly an empty string, compare for strict equality against "" using the === operator: if (strValue === "") { // strValue was empty string } To check for not an empty string strictly, use the !== operator: if (strValue !== "") { // strValue was not an empty string }
For checking if a variable is falsey or if it has length attribute equal to zero (which for a string, means it is empty), I use: function isEmpty(str) { return (!str || str.length === 0 ); } (Note that strings aren't the only variables with a length attribute, arrays have them as well, for example.) Alternativaly, you can use the (not so) newly optional chaining and arrow functions to simplify: const isEmpty = (str) => (!str?.length); It will check the length, returning undefined in case of a nullish value, without throwing an error. In the case of an empty value, zero is falsy and the result is still valid. For checking if a variable is falsey or if the string only contains whitespace or is empty, I use: function isBlank(str) { return (!str || /^\s*$/.test(str)); } If you want, you can monkey-patch the String prototype like this: String.prototype.isEmpty = function() { // This doesn't work the same way as the isEmpty function used // in the first example, it will return true for strings containing only whitespace return (this.length === 0 || !this.trim()); }; console.log("example".isEmpty()); Note that monkey-patching built-in types are controversial, as it can break code that depends on the existing structure of built-in types, for whatever reason.
All the previous answers are good, but this will be even better. Use dual NOT operators (!!): if (!!str) { // Some code here } Or use type casting: if (Boolean(str)) { // Code here } Both do the same function. Typecast the variable to Boolean, where str is a variable. It returns false for null, undefined, 0, 000, "", false. It returns true for all string values other than the empty string (including strings like "0" and " ")
The closest thing you can get to str.Empty (with the precondition that str is a String) is: if (!str.length) { ...
If you need to make sure that the string is not just a bunch of empty spaces (I'm assuming this is for form validation) you need to do a replace on the spaces. if(str.replace(/\s/g,"") == ""){ }
I use: function empty(e) { switch (e) { case "": case 0: case "0": case null: case false: case undefined: return true; default: return false; } } empty(null) // true empty(0) // true empty(7) // false empty("") // true empty((function() { return "" })) // false
Performance I perform tests on macOS v10.13.6 (High Sierra) for 18 chosen solutions. Solutions works slightly different (for corner-case input data) which was presented in the snippet below. Conclusions the simple solutions based on !str,==,=== and length are fast for all browsers (A,B,C,G,I,J) the solutions based on the regular expression (test,replace) and charAt are slowest for all browsers (H,L,M,P) the solutions marked as fastest was fastest only for one test run - but in many runs it changes inside 'fast' solutions group Details In the below snippet I compare results of chosen 18 methods by use different input parameters "" "a" " "- empty string, string with letter and string with space [] {} f- array, object and function 0 1 NaN Infinity - numbers true false - Boolean null undefined Not all tested methods support all input cases. function A(str) { let r=1; if (!str) r=0; return r; } function B(str) { let r=1; if (str == "") r=0; return r; } function C(str) { let r=1; if (str === "") r=0; return r; } function D(str) { let r=1; if(!str || 0 === str.length) r=0; return r; } function E(str) { let r=1; if(!str || /^\s*$/.test(str)) r=0; return r; } function F(str) { let r=1; if(!Boolean(str)) r=0; return r; } function G(str) { let r=1; if(! ((typeof str != 'undefined') && str) ) r=0; return r; } function H(str) { let r=1; if(!/\S/.test(str)) r=0; return r; } function I(str) { let r=1; if (!str.length) r=0; return r; } function J(str) { let r=1; if(str.length <= 0) r=0; return r; } function K(str) { let r=1; if(str.length === 0 || !str.trim()) r=0; return r; } function L(str) { let r=1; if ( str.replace(/\s/g,"") == "") r=0; return r; } function M(str) { let r=1; if((/^\s*$/).test(str)) r=0; return r; } function N(str) { let r=1; if(!str || !str.trim().length) r=0; return r; } function O(str) { let r=1; if(!str || !str.trim()) r=0; return r; } function P(str) { let r=1; if(!str.charAt(0)) r=0; return r; } function Q(str) { let r=1; if(!str || (str.trim()=='')) r=0; return r; } function R(str) { let r=1; if (typeof str == 'undefined' || !str || str.length === 0 || str === "" || !/[^\s]/.test(str) || /^\s*$/.test(str) || str.replace(/\s/g,"") === "") r=0; return r; } // --- TEST --- console.log( ' "" "a" " " [] {} 0 1 NaN Infinity f true false null undefined '); let log1 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)} ${f(null)} ${f(undefined)}`); let log2 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)}`); let log3 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")}`); log1('A', A); log1('B', B); log1('C', C); log1('D', D); log1('E', E); log1('F', F); log1('G', G); log1('H', H); log2('I', I); log2('J', J); log3('K', K); log3('L', L); log3('M', M); log3('N', N); log3('O', O); log3('P', P); log3('Q', Q); log3('R', R); And then for all methods I perform speed test case str = "" for browsers Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0 - you can run tests on your machine here
You can use lodash: _.isEmpty(value). It covers a lot of cases like {}, '', null, undefined, etc. But it always returns true for Number type of JavaScript primitive data types like _.isEmpty(10) or _.isEmpty(Number.MAX_VALUE) both returns true.
Very generic "All-In-One" Function (not recommended though): function is_empty(x) { return ( //don't put newline after return (typeof x == 'undefined') || (x == null) || (x == false) //same as: !x || (x.length == 0) || (x == 0) // note this line, you might not need this. || (x == "") || (x.replace(/\s/g,"") == "") || (!/[^\s]/.test(x)) || (/^\s*$/.test(x)) ); } However, I don't recommend to use that, because your target variable should be of specific type (i.e. string, or numeric, or object?), so apply the checks that are relative to that variable.
var s; // undefined var s = ""; // "" s.length // 0 There's nothing representing an empty string in JavaScript. Do a check against either length (if you know that the var will always be a string) or against ""
Try: if (str && str.trim().length) { //... }
I would not worry too much about the most efficient method. Use what is most clear to your intention. For me that's usually strVar == "". As per the comment from Constantin, if strVar could some how end up containing an integer 0 value, then that would indeed be one of those intention-clarifying situations.
A lot of answers, and a lot of different possibilities! Without a doubt for quick and simple implementation the winner is: if (!str.length) {...} However, as many other examples are available. The best functional method to go about this, I would suggest: function empty(str) { if (typeof str == 'undefined' || !str || str.length === 0 || str === "" || !/[^\s]/.test(str) || /^\s*$/.test(str) || str.replace(/\s/g,"") === "") return true; else return false; } A bit excessive, I know.
check that var a; exist trim out the false spaces in the value, then test for emptiness if ((a)&&(a.trim()!='')) { // if variable a is not empty do this }
You could also go with regular expressions: if((/^\s*$/).test(str)) { } Checks for strings that are either empty or filled with whitespace.
I usually use something like this, if (!str.length) { // Do something }
Also, in case you consider a whitespace filled string as "empty". You can test it with this regular expression: !/\S/.test(string); // Returns true if blank.
If one needs to detect not only empty but also blank strings, I'll add to Goral's answer: function isEmpty(s){ return !s.length; } function isBlank(s){ return isEmpty(s.trim()); }
if ((str?.trim()?.length || 0) > 0) { // str must not be any of: // undefined // null // "" // " " or just whitespace } Or in function form: const isNotNilOrWhitespace = input => (input?.trim()?.length || 0) > 0; const isNilOrWhitespace = input => (input?.trim()?.length || 0) === 0;
Starting with: return (!value || value == undefined || value == "" || value.length == 0); Looking at the last condition, if value == "", its length must be 0. Therefore drop it: return (!value || value == undefined || value == ""); But wait! In JavaScript, an empty string is false. Therefore, drop value == "": return (!value || value == undefined); And !undefined is true, so that check isn't needed. So we have: return (!value); And we don't need parentheses: return !value
I use a combination, and the fastest checks are first. function isBlank(pString) { if (!pString) { return true; } // Checks for a non-white space character // which I think [citation needed] is faster // than removing all the whitespace and checking // against an empty string return !/[^\s]+/.test(pString); }
I have not noticed an answer that takes into account the possibility of null characters in a string. For example, if we have a null character string: var y = "\0"; // an empty string, but has a null character (y === "") // false, testing against an empty string does not work (y.length === 0) // false (y) // true, this is also not expected (y.match(/^[\s]*$/)) // false, again not wanted To test its nullness one could do something like this: String.prototype.isNull = function(){ return Boolean(this.match(/^[\0]*$/)); } ... "\0".isNull() // true It works on a null string, and on an empty string and it is accessible for all strings. In addition, it could be expanded to contain other JavaScript empty or whitespace characters (i.e. nonbreaking space, byte order mark, line/paragraph separator, etc.).
Meanwhile we can have one function that checks for all 'empties' like null, undefined, '', ' ', {}, []. So I just wrote this. var isEmpty = function(data) { if(typeof(data) === 'object'){ if(JSON.stringify(data) === '{}' || JSON.stringify(data) === '[]'){ return true; }else if(!data){ return true; } return false; }else if(typeof(data) === 'string'){ if(!data.trim()){ return true; } return false; }else if(typeof(data) === 'undefined'){ return true; }else{ return false; } } Use cases and results. console.log(isEmpty()); // true console.log(isEmpty(null)); // true console.log(isEmpty('')); // true console.log(isEmpty(' ')); // true console.log(isEmpty(undefined)); // true console.log(isEmpty({})); // true console.log(isEmpty([])); // true console.log(isEmpty(0)); // false console.log(isEmpty('Hey')); // false
I did some research on what happens if you pass a non-string and non-empty/null value to a tester function. As many know, (0 == "") is true in JavaScript, but since 0 is a value and not empty or null, you may want to test for it. The following two functions return true only for undefined, null, empty/whitespace values and false for everything else, such as numbers, Boolean, objects, expressions, etc. function IsNullOrEmpty(value) { return (value == null || value === ""); } function IsNullOrWhiteSpace(value) { return (value == null || !/\S/.test(value)); } More complicated examples exists, but these are simple and give consistent results. There is no need to test for undefined, since it's included in (value == null) check. You may also mimic C# behaviour by adding them to String like this: String.IsNullOrEmpty = function (value) { ... } You do not want to put it in Strings prototype, because if the instance of the String-class is null, it will error: String.prototype.IsNullOrEmpty = function (value) { ... } var myvar = null; if (1 == 2) { myvar = "OK"; } // Could be set myvar.IsNullOrEmpty(); // Throws error I tested with the following value array. You can loop it through to test your functions if in doubt. // Helper items var MyClass = function (b) { this.a = "Hello World!"; this.b = b; }; MyClass.prototype.hello = function () { if (this.b == null) { alert(this.a); } else { alert(this.b); } }; var z; var arr = [ // 0: Explanation for printing, 1: actual value ['undefined', undefined], ['(var) z', z], ['null', null], ['empty', ''], ['space', ' '], ['tab', '\t'], ['newline', '\n'], ['carriage return', '\r'], ['"\\r\\n"', '\r\n'], ['"\\n\\r"', '\n\r'], ['" \\t \\n "', ' \t \n '], ['" txt \\t test \\n"', ' txt \t test \n'], ['"txt"', "txt"], ['"undefined"', 'undefined'], ['"null"', 'null'], ['"0"', '0'], ['"1"', '1'], ['"1.5"', '1.5'], ['"1,5"', '1,5'], // Valid number in some locales, not in JavaScript ['comma', ','], ['dot', '.'], ['".5"', '.5'], ['0', 0], ['0.0', 0.0], ['1', 1], ['1.5', 1.5], ['NaN', NaN], ['/\S/', /\S/], ['true', true], ['false', false], ['function, returns true', function () { return true; } ], ['function, returns false', function () { return false; } ], ['function, returns null', function () { return null; } ], ['function, returns string', function () { return "test"; } ], ['function, returns undefined', function () { } ], ['MyClass', MyClass], ['new MyClass', new MyClass()], ['empty object', {}], ['non-empty object', { a: "a", match: "bogus", test: "bogus"}], ['object with toString: string', { a: "a", match: "bogus", test: "bogus", toString: function () { return "test"; } }], ['object with toString: null', { a: "a", match: "bogus", test: "bogus", toString: function () { return null; } }] ];
I didn't see a good answer here (at least not an answer that fits for me) So I decided to answer myself: value === undefined || value === null || value === ""; You need to start checking if it's undefined. Otherwise your method can explode, and then you can check if it equals null or is equal to an empty string. You cannot have !! or only if(value) since if you check 0 it's going to give you a false answer (0 is false). With that said, wrap it up in a method like: public static isEmpty(value: any): boolean { return value === undefined || value === null || value === ""; } PS.: You don't need to check typeof, since it would explode and throw even before it enters the method
Trimming whitespace with the null-coalescing operator: if (!str?.trim()) { // do something... }
There is a lot of useful information here, but in my opinion, one of the most important elements was not addressed. null, undefined, and "" are all falsy. When evaluating for an empty string, it's often because you need to replace it with something else. In which case, you can expect the following behavior. var a = "" var b = null var c = undefined console.log(a || "falsy string provided") // prints ->"falsy string provided" console.log(b || "falsy string provided") // prints ->"falsy string provided" console.log(c || "falsy string provided") // prints ->"falsy string provided" With that in mind, a method or function that can return whether or not a string is "", null, or undefined (an invalid string) versus a valid string is as simple as this: const validStr = (str) => str ? true : false validStr(undefined) // returns false validStr(null) // returns false validStr("") // returns false validStr("My String") // returns true
Try this: export const isEmpty = string => (!string || !string.length);
All these answers are nice. But I cannot be sure that variable is a string, doesn't contain only spaces (this is important for me), and can contain '0' (string). My version: function empty(str){ return !str || !/[^\s]+/.test(str); } empty(null); // true empty(0); // true empty(7); // false empty(""); // true empty("0"); // false empty(" "); // true Sample on jsfiddle.
There's no isEmpty() method, you have to check for the type and the length: if (typeof test === 'string' && test.length === 0){ ... The type check is needed in order to avoid runtime errors when test is undefined or null.
Yadcf - Server side multi select
I used the function yadcf multi_select When I make my search for two words, the function puts me a pipe between. I do not know how to remove it for that he understands the two words separately. http://www.hostingpics.net/viewer.php?id=710742Capture.jpg I found that the pipe would begin with this function : function doFilterMultiSelect(arg, table_selector_jq_friendly, column_number, filter_match_mode) { $.fn.dataTableExt.iApiIndex = oTablesIndex[table_selector_jq_friendly]; var oTable = oTables[table_selector_jq_friendly], selected_values = $(arg).val(), selected_values_trimmed = [], i, stringForSearch, column_number_filter, settingsDt = getSettingsObjFromTable(oTable); column_number_filter = calcColumnNumberFilter(settingsDt, column_number, table_selector_jq_friendly); $(document).data("#yadcf-filter-" + table_selector_jq_friendly + "-" + column_number + "_val", selected_values); if (selected_values !== null) { for (i = selected_values.length - 1; i >= 0; i--) { if (selected_values[i] === "-1") { selected_values.splice(i, 1); break; } } for (i = 0; i < selected_values.length; i++) { selected_values_trimmed.push($.trim(selected_values[i])); } if (selected_values_trimmed.length !== 0) { stringForSearch = selected_values_trimmed.join('narutouzomaki'); stringForSearch = stringForSearch.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); stringForSearch = stringForSearch.split('narutouzomaki').join('|'); if (filter_match_mode === "contains") { oTable.fnFilter(stringForSearch, column_number_filter, true, false, true); } else if (filter_match_mode === "exact") { oTable.fnFilter("^(" + stringForSearch + ")$", column_number_filter, true, false, true); } else if (filter_match_mode === "startsWith") { oTable.fnFilter("^(" + stringForSearch + ")", column_number_filter, true, false, true); } else if (filter_match_mode === "regex") { oTable.fnFilter(stringForSearch, column_number_filter, true, false, true); } } else { oTable.fnFilter("", column_number_filter); } } else { oTable.fnFilter("", column_number_filter); } resetIApiIndex(); } I can not seem to solve the problem to operate the multi_select. Thank you for the help
Since you are using a multi select filter on some column yadcf sends strings with | (OR) to your server. On your server side you have to do the split of the string into array/list of string and construct a proper sql query. Split in Java Split in PHP(see code sample in bottom p.s I'm the author of yadcf
Format Textbox input for phone number MVC
I am simply using a #Html.TextBoxFor(m => m.PhoneNumber, new { id = "phoneNo") I am using a regex to limit it to 10 numbers only. Is there a way I can format the textbox to appear like (555) 444-3333 while they type, but in the model it will simply be passing the 10 numbers, like 5554443333? I meant to automatically create those brackets and - while also checking using regex if they entered 10 numbers?
You can do it with jquery as Matt said at his comment, stated at this question of the site: Phone mask with jQuery and Masked Input Plugin Or with plain javascript, as explained by xxx here with alternatives too: Mask US phone number string with JavaScript List of alternatives coded for a example input called "phone": Example code with plain javaScript: document.getElementById('phone').addEventListener('input', function (e) { var x = e.target.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/); e.target.value = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3] : ''); }); Example code with jQuery but without adding any new dependence(): $('#phone', '#example-form') .keydown(function (e) { var key = e.which || e.charCode || e.keyCode || 0; $phone = $(this); // Don't let them remove the starting '(' if ($phone.val().length === 1 && (key === 8 || key === 46)) { $phone.val('('); return false; } // Reset if they highlight and type over first char. else if ($phone.val().charAt(0) !== '(') { $phone.val('('+$phone.val()); } // Auto-format- do not expose the mask as the user begins to type if (key !== 8 && key !== 9) { if ($phone.val().length === 4) { $phone.val($phone.val() + ')'); } if ($phone.val().length === 5) { $phone.val($phone.val() + ' '); } if ($phone.val().length === 9) { $phone.val($phone.val() + '-'); } } // Allow numeric (and tab, backspace, delete) keys only return (key == 8 || key == 9 || key == 46 || (key >= 48 && key <= 57) || (key >= 96 && key <= 105)); }) .bind('focus click', function () { $phone = $(this); if ($phone.val().length === 0) { $phone.val('('); } else { var val = $phone.val(); $phone.val('').val(val); // Ensure cursor remains at the end } }) .blur(function () { $phone = $(this); if ($phone.val() === '(') { $phone.val(''); } }); Example code with jQuery using Masked Input Plugin: $("#phone").mask("(99) 9999?9-9999"); $("#phone").on("blur", function() { var last = $(this).val().substr( $(this).val().indexOf("-") + 1 ); if( last.length == 3 ) { var move = $(this).val().substr( $(this).val().indexOf("-") - 1, 1 ); var lastfour = move + last; var first = $(this).val().substr( 0, 9 ); $(this).val( first + '-' + lastfour ); } });