Safest delimiter or convert from javascript hashmap to java linked map? - javascript

I have data like this, TITLE is the name of variable and below it is the string data (Please note the data can be different sometimes)
TITLE1
abcd
TITLE2
abcde
TITLE3
acd,sdssds!###$#$#%$%$^&**()aas
Now, I want to to send these three to java and want to make a linked map from them I did like this
JAVASCRIPT
var string = "TITLE1=abcd, TITLE2=abcde, TITLE3=acd,sdssds!###$#$#%$%$^&**()aas"
and used it in java as
JAVA
LinkedHashMap <String, String> selectedCheckBoxMap = new LinkedHashMap <String, String> ();
String[] pairs = selectedCheckBoxTokens.split (",");
for (int i = 0; i < pairs.length; i++)
{
String pair = pairs[i];
String[] keyValue = pair.split ("=");
selectedCheckBoxMap.put (keyValue[0], keyValue[1]);
}
But this breaks on "," as delimiter as TITLE3 already has character ','
I then used this character instead of "," as delimiter "‡", but this not a good approach.
What should I do ? Should I change it to hashmap in javascript ? But how to convert hashmap from javascript to JAVA directly ? Or should I use some other delimiter ?
The delimiter should be character that we cannot type or ever come across in text.
Thanks,
Aiden

if your data is that regular you could split on a ", " instead.
if spaces are in your value sets, then you need to mark your data values... be that with single/double quotes or some other unique marker.
building a JSON object and then delivering it would likely be a more robust solution.

If you use JSON:
var s = {};
s["TITLE1"] = "skladjdklsajdsla";
s["TITLE2"] = "*&^&^%&*,,()*&";
s["TITLE3"] = "acd,sdssds!###$#$#%$%$^&**()aas";
That code will create an Java Script Object:
Object {
TITLE1="skladjdklsajdsla",
TITLE2="*&^&^%&*,,()*&",
TITLE3="acd,sdssds!###$#$#%$%$^&**()aas"
}
You can parse the Object using a JSON library for Java:
http://www.oracle.com/technetwork/articles/java/json-1973242.html
See: How to parse JSON in Java
JSON Standard: http://www.json.org/

When generating the string to be send, escape the commas and the equal signs in the values by replacing them with something else like %2C and %3D
Then or server side unescape by doing
selectedCheckBoxMap.put (keyValue[0], keyValue[1].replace("%2C",",").replace("%3D","="));

Using common characters as a delimiter is error-prawn ever since. You have to escape each delimiter you use and then parse the string by yourself. This means, that you have to call value.replace(/([\\=,])/g, '\\$1') on each entry, before appending it to your datastring.
Even if i would recommend you using JSON, as Alzoid proposed, here is an untested implementation you could use to decode the input (assuming '\' is your escape character):
boolean escaped = false;
boolean waitingForKey = true;
String key = "";
String current = "";
for (int i = 0; i < data.length(); i++) {
char character = data.charAt(i);
if (escaped) {
current += character;
escaped = false;
continue;
}
if (waitingForKey && Character.isWhitespace(character)) {
continue;
} else if (waitingForKey) {
waitingForKey = false;
}
switch (character) {
case '\\':
escaped = true;
break;
case '=':
key = current;
current = "";
break;
case ',':
map.put(key, current);
current = "";
key = "";
waitingForKey = true;
break;
default:
current += character;
}
}
if (!data.isEmpty()) {
map.put(key, current);
}

Related

Writing a Hexadecimal Escape Character Sequence using Variables

Testing Hex Character Codes
Problem
What does a Vertical Tab or a Backspace character actually do? I want to find out.
My experiment is to find out exactly what happens when every hex character is put into a string. I thought the best way to do this would be to created a nested loop to go through each of the 16 hexadecimal characters to create each possible 2 digit hex character code.
I soon discovered that you cannot use the \x escape character with interpolated variables, and so I expect what I have set out to do might be impossible.
const hexCharacters = "0123456789ABCDEF";
let code = "";
let char1 = "";
let char2 = "";
for (charPos1 = 0; charPos1 < hexCharacters.length; charPos1++) {
for (charPos2 = 0; charPos2 < hexCharacters.length; charPos2++) {
char1 = hexCharacters[charPos1];
char2 = hexCharacters[charPos2];
code = `${char1}${char2}`;
printHexChar(code);
}
}
function printHexChar(string) {
let output = `<p>Hex Code ${string} = \x${string}</p>`; // THE PROBLEM IS CLEAR
document.write(output)
}
I know it will also probably fail once it gets past 7F or whichever is the last character in the set, but that's not the main issue here! :D
Potential solution
string.prototype.fromCharCode
This sort of string method approach would seem to be the answer, but it is meant for U-16 character codes, and that is not what I wanted to test. There doesn't seem to be an existing string method for hex codes. Probably because nobody would ever want one, but nevertheless it would be cool.
Conclusion
Is there any way to create an escape character sequence from assembled parts that will render not as plain text, but as a proper escape character sequence?
Apologies if this has been asked before in some form, but with my feeble understanding of things I just couldn't find an answer.
You can use String.fromCharCode with parseInt.
`<p>Hex Code ${string} = ${String.fromCharCode(parseInt(string, 16))}</p>`;
const hexCharacters = "0123456789ABCDEF";
let code = "";
let char1 = "";
let char2 = "";
for (charPos1 = 0; charPos1 < hexCharacters.length; charPos1++) {
for (charPos2 = 0; charPos2 < hexCharacters.length; charPos2++) {
char1 = hexCharacters[charPos1];
char2 = hexCharacters[charPos2];
code = `${char1}${char2}`;
printHexChar(code);
}
}
function printHexChar(string) {
let output = `<p>Hex Code ${string} = ${String.fromCharCode(parseInt(string, 16))}</p>`;
document.write(output)
}
eval works as well, though it should generally be avoided.
`<p>Hex Code ${string} = ${eval('"\\x'+string+'"')}</p>`
If you want to output \x literally, then in a string literal you need to escape the escape character, so `\\x`.
string.prototype.fromCharCode [...] is meant for U-16 character codes
JavaScript uses one character encoding. The following strings are all equal:
let a = String.fromCharCode(27);
let b = "\x1B";
let c = "\u001B";
console.log(a === b, b === c);
If I understand correctly, you want to produce a string literal that shows \x escape sequences -- not the actual character:
// Prepare string
let chars = Array.from({length: 128}, (_, i) => String.fromCharCode(i))
.join("");
// Escape them
let escaped = Array.from(chars, ch => `\\x${ch.charCodeAt().toString(16).padStart(2, "0")}`).join("");
console.log(escaped);
But you might also use JSON.stringify. Although it uses different escape sequences (\u instead of \x), and only for non-display characters, it will be the exact same string when evaluated. Here is a demo:
// Prepare string
let chars = Array.from({length: 128}, (_, i) => String.fromCharCode(i))
.join("");
// Escape them
let escaped = '"' + Array.from(chars, ch => `\\x${ch.charCodeAt().toString(16).padStart(2, "0")}`).join("") + '"';
console.log(escaped);
// Or JSONify them
let json = JSON.stringify(chars);
console.log(json);
// Compare them, when evaluated:
console.log(eval(escaped) === eval(json));
Finally, note that there is nothing special about hexadecimal: it is just a representation of an integer. In the end, it is the numerical value that is important, not the representation of it. It is that numerical value that corresponds to a character.
Addendum
If you prefer code that sticks to old-style JavaScript, here is something equivalent of the last code snippet:
// Prepare string
let chars = "";
for (let i = 0; i < 128; i++) {
chars += String.fromCharCode(i);
}
// Escape the characters in this string
let escaped = '"';
for (let i = 0; i < chars.length; i++) {
let ch = chars.charCodeAt(i);
let hex = ch.toString(16);
if (hex.length === 1) hex = "0" + hex;
escaped += "\\x" + hex;
}
escaped += '"';
console.log(escaped);
// Or JSONify them
let json = JSON.stringify(chars);
console.log(json);
// Compare them, when evaluated:
console.log(eval(escaped) === eval(json));

How to convert non numeric string to int

For an assignment, i am trying to recreate a small project I once made in ASP.NET.
It converted each letter of a text to its int value, then added 1 en reconverted it to a char and put them all back into a single string.
Now I am trying to do this in Angular, but I am having trouble converting my non-numeric strings to its int value.
I tried it with ParseInt(), but this only seems to work if the string is a valid integer.
Is there any way to parse or convert non-numeric strings to an int value and how?
'String here'.split('').map(function (char) {
return String.fromCharCode(char.charCodeAt(0) + 1);
}).join('');
If you mean char code.
Thankx to the helpful insights of Claies and Damien Czapiewski I constructed the following solution.
Loop through each character in my string in a for loop.
Then, for each char I retrieved its value with charCodeAt()
And to return to a string value I used fromCharCode()
encode(msg:string):string {
let result: string = "";
if (msg) {
for (var i = 0; i < msg.length; i++) {
let msgToInt = msg.charCodeAt(i);
// do stuff here
result += String.fromCharCode(msgToInt);
}
}
return result;
}

User customizable regex expression for string formatting

We have a web-app that allows clients to import some CSV data into our database, e.g. a list of products they sell.
The problem is, we'd like to store their data as-is but let the user specify a custom expression so that when they view the data it looks a bit nicer.
Some imported data might look like this:
product_label,quantity
A: Product1- 001,50
A: Product2- 001,80
A: Product3- 001,150
B: Product5- 001,100
In this case, the client might want to strip out the prefix 'A: ' and the suffix ' - 001' in the string 'A: Product1- 001' so that just 'Product1' is displayed.
The problem is, every client seems to have a different string format and desired output format.
I was thinking of providing the ability to specify a regex to format the string purely on the client-side using javascript but I'm not sure how I would use this regex and how to allow them to specify grouping or back-references.
Any suggestions on how to let them specify their own format? e.g. something like:
match_pattern = ... // input field text (escaped into a regex)
output_pattern = ... // How to let them specify the output from the match results?
display_string = applyFormatting(string, match_pattern, output_pattern);
Here's some Regex to split the string up.
// Set the original string
var strOriginal = 'B: Product5- 001,100';
// Settings to specify which parts they want
var bln = [];
bln[0] = true;
bln[1] = true;
bln[2] = false;
bln[3] = false;
// Split the orginal string up
var str = []
str[0] = strOriginal.replace(/([A-Z]\:\s)([A-Za-z0-9]+?)(\-\s[\d]+?)(\,[\d]+)/,'$1');
str[1] = strOriginal.replace(/([A-Z]\:\s)([A-Za-z0-9]+?)(\-\s[\d]+?)(\,[\d]+)/,'$2');
str[2] = strOriginal.replace(/([A-Z]\:\s)([A-Za-z0-9]+?)(\-\s[\d]+?)(\,[\d]+)/,'$3');
str[3] = strOriginal.replace(/([A-Z]\:\s)([A-Za-z0-9]+?)(\-\s[\d]+?)(\,[\d]+)/,'$4');
var strOutput = '';
for (i = 0; i < str.length; i++) {
if (bln[i]) {
strOutput += str[i] + '<br />';
}
}
document.getElementById('test').innerHTML = strOutput;
<div id="test"></div>

I want to remove comma between two double quote and allowed space between two double quote

I have one search string like txtKeyword and it will accept all the below case for highlighting skills
1.C# JAVA
2."C#" AND "JAVA"
5.C# "JAVA"
6.C#,'JAVA'
7.C#,"JAVA"
8.C#,"JAVA",'PHP'
9.C#,"JAVA" AND PHP
In all above case C# and JAVA are highlighted..but for
"MY SQL","SQL SERVER"
it will not highlight MY SQL and SQL SERVER because of space between two double quote
so final array is like ["MY,SQL,SQL,SERVER"]
But i need final array like ["MY SQL,SQL SERVER,C#,Java"]
Question in logical terms-
I want to remove comma between two double quote and allowed space between two double quote,and remove all spaces outside two double quote and split array with comma
Here is my code snippet
//Grab basic search string on resume result list
var grabBasicSearchKeyword = $("#txtKeyword").val();
if (grabBasicSearchKeyword!=null)
{
//Remove Unnecessary Characters From Basic Search String
var finalBasicSearchString = grabBasicSearchKeyword.replace(/[`~!#$%^&*()_|\-=?;:'"<>\{\}\[\]\\\/]/gi, '');
//Check And Remove: "OR","AND","NOT","or","and" & "not" From Basic Search String
if (finalBasicSearchString.indexOf('OR') || finalBasicSearchString.indexOf('AND') || finalBasicSearchString.indexOf('NOT') || finalBasicSearchString.indexOf('or') || finalBasicSearchString.indexOf('and') || finalBasicSearchString.indexOf('not'))
{
var findOR = finalBasicSearchString.replace(/OR/g, ' ');
var findor = findOR.replace(/or/g, ' ');
var findAND = findor.replace(/AND/g, ' ');
var findand = findAND.replace(/and/g, ' ');
var findNOT = findand.replace(/NOT/g, ' ');
var findnot = findNOT.replace(/not/g, ' ');
var removeDoubleQuote = findnot.replace(/"/g, '');
var removeBackSlash = removeDoubleQuote.replace(/\\/g, '');
var removeComma = removeBackSlash.replace(/,/g, ' ');
var finalArray = removeComma.split(" ");
for (var j = 0; j < finalArray.length; j++) {
if (masterSkillArray.contains(finalArray[j])) {
basicSearchHighlightArray.push(finalArray[j]);
}
}
$(".skil-list").highlight(basicSearchHighlightArray);
$(".post").highlight(basicSearchHighlightArray);
}
}
You'll want to use the 'ignore case' flag i for your logical operator patterns to cut down on the duplicate regexing.
You can do all of the logical replacements in a single regex - /\b(?:OR|AND|NOT)\b/gi (the i flag making the matches case insensitive).
You'll need to treat quoted strings separately. In this fiddle the quoted strings are matched and used to create a new string with only those terms. A second new string is then created by removing the quoted strings from the original input (as well as commas). The strings are then appended and split on ,.
As shown by the fiddle, rather than creating several variables, you can simply chain your replacements.

Javascript split only once and ignore the rest

I am parsing some key value pairs that are separated by colons. The problem I am having is that in the value section there are colons that I want to ignore but the split function is picking them up anyway.
sample:
Name: my name
description: this string is not escaped: i hate these colons
date: a date
On the individual lines I tried this line.split(/:/, 1) but it only matched the value part of the data. Next I tried line.split(/:/, 2) but that gave me ['description', 'this string is not escaped'] and I need the whole string.
Thanks for the help!
a = line.split(/:/);
key = a.shift();
val = a.join(':');
Use the greedy operator (?) to only split the first instance.
line.split(/: (.+)?/, 2);
If you prefer an alternative to regexp consider this:
var split = line.split(':');
var key = split[0];
var val = split.slice(1).join(":");
Reference: split, slice, join.
Slightly more elegant:
a = line.match(/(.*?):(.*)/);
key = a[1];
val = a[2];
May be this approach will be the best for such purpose:
var a = line.match(/([^:\s]+)\s*:\s*(.*)/);
var key = a[1];
var val = a[2];
So, you can use tabulations in your config/data files of such structure and also not worry about spaces before or after your name-value delimiter ':'.
Or you can use primitive and fast string functions indexOf and substr to reach your goal in, I think, the fastest way (by CPU and RAM)
for ( ... line ... ) {
var delimPos = line.indexOf(':');
if (delimPos <= 0) {
continue; // Something wrong with this "line"
}
var key = line.substr(0, delimPos).trim();
var val = line.substr(delimPos + 1).trim();
// Do all you need with this key: val
}
Split string in two at first occurrence
To split a string with multiple i.e. columns : only at the first column occurrence
use Positive Lookbehind (?<=)
const a = "Description: this: is: nice";
const b = "Name: My Name";
console.log(a.split(/(?<=^[^:]*):/)); // ["Description", " this: is: nice"]
console.log(b.split(/(?<=^[^:]*):/)); // ["Name", " My Name"]
it basically consumes from Start of string ^ everything that is not a column [^:] zero or more times *. Once the positive lookbehind is done, finally matches the column :.
If you additionally want to remove one or more whitespaces following the column,
use /(?<=^[^:]*): */
Explanation on Regex101.com
function splitOnce(str, sep) {
const idx = str.indexOf(sep);
return [str.slice(0, idx), str.slice(idx+1)];
}
splitOnce("description: this string is not escaped: i hate these colons", ":")

Categories

Resources