Related
I would like to parse that string:
[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]
In order to have a key value (JSON)
{
"abc.d.2": "mcnv.3.we",
"abec.d.2: "mcnv.4.we",
"abhc.d.2": "mcnv.5.we"
}
First I would like to check if string can be parse to make it key=>value.
How can I check the string if it contains pairs?
Thanks
You can try something like this:
Approach 1:
Idea:
Update the regex to have more specific characters. In your case, alphanumeric and period.
Get all matching elements from string.
All odd values are keys and even matches are values.
Loop over matches and create an object.
const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/[\w\.\d]+/gi);
const output = {};
for(var i = 0; i< matches.length; i+=2) {
output[matches[i]] = matches[i+1];
}
console.log(output)
Approach 2:
Idea:
Write a regex to capture each individual group: [...:...]
Then eliminate braces [ and ].
Split string using comma ,.
First part is your key. Second is your value.
const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/\[([\w\d\.,]*)\]/gi);
const output = matches.reduce((obj, match) => {
const parts = match.substring(1, match.length - 1).split(',');
obj[parts[0]] = parts[1];
return obj;
}, {})
console.log(output)
In above approach, you can also include Map. The iteration can be bit confusing initially, but you can try.
const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/\[([\w\d\.,]*)\]/gi);
const output = matches.reduce((obj, match) => {
const parts = match.substring(1, match.length - 1).split(',');
obj.set(...parts)
return obj;
}, new Map())
for (const [k, v] of output.entries()) {
console.log(`Key: ${k}, value: ${v}`)
}
Parse the array as JSON, iterate over the array, adding entries to the target object as you go, watch out for duplicate keys:
let dict_target = {}; // The target dictionary,
let src, arysrc, proceed = false;
try {
src = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]"
.replace(/,/g, '","')
.replace(/\]","\[/g, '"],["')
.replace(/^\[\[/, '[["')
.replace(/\]\]$/, '"]]')
;
arysrc = JSON.parse(src);
proceed = true; // Could parse the data, can carry on with processing the data
} catch (e) {
console.log(`Source data unparseable, error '${e.message}'.`);
}
if (proceed) {
arysrc.forEach ( (a_item, n_idx) => {
if (dict_target.hasOwnProperty(a_item[0])) {
// add any tests and processing for duplicate keys/value pairs here
if (typeof dict_target[a_item[0]] === "string") {
dict_target[a_item[0]] = [ dict_target[a_item[0]] ];
}
dict_target[a_item[0]].push(a_item[1]);
}
else {
dict_target[a_item[0]] = a_item[1];
}
});
} // if -- proceed
My coding golf solution...
const parse = (str) => {
let obj = {};
str.replace(
/\[([^\[,]+),([^\],]+)\]/g,
(m, k, v) => obj[k] = v
);
return obj;
};
Advantages:
More Permissive of arbitrary chars
More Tolerant of missing values
Avoids disposable objects for GC
Disadvantages:
More Permissive of arbitrary chars!
This is not a proper parser...
Does not have context, just [key,val]
I actually wanted to post the following as my answer... but I think it'll get me in trouble :P
const parse=(str,obj={})=>
!str.replace(/\[([^\[,]+),([^\],]+)\]/g,(m,k,v)=>obj[k]=v)||obj;
Here's the code which validates the string first and outputs the result. Not at all optimal but does the task just fine.
var string = '[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]';
var result = (/^\[(\[.*\..*\..*\,.*\..*\..*\]\,)*\[(.*\..*\..*\,.*\..*\..*)\]\]$/g).exec(string);
if (result) {
var r1 = result[1].replace(/\[|\]/g, '').split(',');
var r2 = result[2].split(',');
var output = {};
for (var i = 0; i < r1.length -1; i +=2) {
output[r1[i]] = r1[i+1];
}
output[r2[0]] = r2[1];
console.log(output);
} else {
console.log('invalid string');
}
I have a string similiar to document.cookie:
var str = 'foo=bar, baz=quux';
Converting it into an array is very easy:
str = str.split(', ');
for (var i = 0; i < str.length; i++) {
str[i].split('=');
}
It produces something like this:
[['foo', 'bar'], ['baz', 'quux']]
Converting to an object (which would be more appropriate in this case) is harder.
str = JSON.parse('{' + str.replace('=', ':') + '}');
This produces an object like this, which is invalid:
{foo: bar, baz: quux}
I want an object like this:
{'foo': 'bar', 'baz': 'quux'}
Note: I've used single quotes in my examples, but when posting your code, if you're using JSON.parse(), keep in your mind that it requires double quotes instead of single.
Update
Thanks for everybody. Here's the function I'll use (for future reference):
function str_obj(str) {
str = str.split(', ');
var result = {};
for (var i = 0; i < str.length; i++) {
var cur = str[i].split('=');
result[cur[0]] = cur[1];
}
return result;
}
The shortest way
document.cookie.split('; ').reduce((prev, current) => {
const [name, ...value] = current.split('=');
prev[name] = value.join('=');
return prev;
}, {});
Why exactly do you need JSON.parse in here? Modifying your arrays example
let str = "foo=bar; baz=quux";
str = str.split('; ');
const result = {};
for (let i in str) {
const cur = str[i].split('=');
result[cur[0]] = cur[1];
}
console.log(result);
note : The document.cookie (question headline) is semicolon separated and not comma separated (question) ...
An alternative using reduce :
var str = 'foo=bar; baz=quux';
var obj = str.split(/[;] */).reduce(function(result, pairStr) {
var arr = pairStr.split('=');
if (arr.length === 2) { result[arr[0]] = arr[1]; }
return result;
}, {});
A way to parse cookies using native methods like URLSearchParams and Object.fromEntries, avoiding loops and temporary variables.
Parsing document.cookie:
Object.fromEntries(new URLSearchParams(document.cookie.replace(/; /g, "&")))
For the scope of the question (cookies are separated by , and stored in variable str)
Object.fromEntries(new URLSearchParams(str.replace(/, /g, "&")))
Given an array a containing your intermediate form:
[['foo', 'bar'], ['baz', 'quux']]
then simply:
var obj = {};
for (var i = 0; i < a.length; ++i) {
var tmp = a[i];
obj[tmp[0]] = tmp[1];
}
To convert it to an object, just do that from the beginning:
var obj = {};
str = str.split(', ');
for (var i = 0; i < str.length; i++) {
var tmp = str[i].split('=');
obj[tmp[0]] = tmp[1];
}
Then, if you want JSON out of it:
var jsonString = JSON.stringify(obj);
parse cookies (IE9+):
document.cookie.split('; ').reduce((result, v) => {
const k = v.split('=');
result[k[0]] = k[1];
return result;
}, {})
I'm a fan of John Resig's "Search and don't replace" method for this sort of thing:
var str = 'foo=bar, baz=quux',
arr = [],
res = '{';
str.replace(/([^\s,=]+)=([^,]+)(?=,|$)/g, function ($0, key, value) {
arr.push('"' + key + '":"' + value + '"');
});
res += arr.join(",") + "}";
alert(res);
Working example: http://jsfiddle.net/cm6MT/.
Makes things a lot simpler without the need for JSON support. Of course, it's just as easy to use the same regular expression with exec() or match().
Whoops, I thought you wanted to convert to a JSON string, not an object. In that case, you only need to modify the code slightly:
var str = 'foo=bar, baz=quux',
res = {};
str.replace(/([^\s,=]+)=([^,]+)(?=,|$)/g, function ($0, key, value) {
res[key] = value;
});
console.log(res.foo);
//-> "bar"
Working example 2: http://jsfiddle.net/cm6MT/1/
Most of the above solutions fail with the __gads cookie that Google sets because it uses a '=' character in the cookie value.
The solution is to use a regular expression instead of calling split('='):
document.cookie.split(';').reduce((prev, current) => {
const [name, value] = current.split(/\s?(.*?)=(.*)/).splice(1, 2);
prev[name] = value;
return prev;
}, {});
That's pretty crappy data, as long as its not using ,= this would work on that data
var text = 'foo=bar, baz=quux',
pattern = new RegExp(/\b([^=,]+)=([^=,]+)\b/g),
obj = {};
while (match = pattern.exec(text)) obj[match[1]] = match[2];
console.dir(obj);
An alternate version of your updated solution that checks for the null/empty string and just returns an empty object and also allows for custom delimiters.
function stringToObject(str, delimiter) {
var result = {};
if (str && str.length > 0) {
str = str.split(delimiter || ',');
for (var i = 0; i < str.length; i++) {
var cur = str[i].split('=');
result[cur[0]] = cur[1];
}
}
return result;
}
first thing that occurred to me, I'll leave it as the original version, but cookies should not be empty otherwise there will be a json parse error
JSON.parse(`{"${document.cookie.replace(/=/g,'":"').replace(/; /g,'","')}"}`)
fast and reliable version - cookie to object
let c=document.cookie.split('; '),i=c.length,o={};
while(i--){let a=c[i].split('=');o[a[0]]=a[1]}
and short function for get single cookie
getCookie=e=>(e=document.cookie.match(e+'=([^;]+)'),e&&e[1])
function getCookie(){
var o=document.cookie.split("; ");
var r=[{}];
for(var i=0;i<o.length;i++){
r[o[i].split("=")[0]] = o[i].split("=")[1];
}
return r;
}
Just call getCookie() and it will return all cookies from the current website.
If you have a cookie called 'mycookie' you can run getCookie()['mycookie']; and it will return the value of the cookie 'mycookie'.
There is also a One-Line option:
function getCookie(){var o=document.cookie.split("; ");var r=[{}];for(var i=0;i<o.length;i++){r[o[i].split("=")[0]] = o[i].split("=")[1];}return r;}
This one can be used with the same methods as above.
I have a string like:
const stringVar = ":20:9077f1722efa3632 :12:700 :77E: :27A:2/2 :21A:9077f1722efa3632 :27:1/2 :40A:IRREVOCABLE"
I want to create JSON from above stringVar:
{
":21:" : "9077f1722efa3632",
":12:" : "700",
":27A:": "2/2",
":21A:": "9077f1722efa3632",
":27:" : "1/2",
":40A:": "IRREVOCABLE"
}
So, I was thinking I could split with regular expression (":(any Of char/digit):")
I would make the first part the key and the second part its value.
The regular expression /(:\w+:)(\S+)/ matches the whole key:value pair. You can add the g modifier, and then use it in a loop to get all the matches and put them into the object.
const stringVar = ":20:9077f1722efa3632 :12:700 :77E: :27A:2/2 :21A:9077f1722efa3632 :27:1/2 :40A:IRREVOCABLE"
var regexp = /(:\w+:)(\S+)/g;
var obj = {};
var match;
while (match = regexp.exec(stringVar)) {
obj[match[1]] = match[2];
}
console.log(obj);
If you want to create an array of {key: ":20:", value: "9077f1722efa3632"}, you can modify the code to:
const stringVar = ":20:9077f1722efa3632 :12:700 :77E: :27A:2/2 :21A:9077f1722efa3632 :27:1/2 :40A:IRREVOCABLE"
var regexp = /(:\w+:)(\S+)/g;
var array = [];
var match;
while (match = regexp.exec(stringVar)) {
array.push({key: match[1], value: match[2]});
}
console.log(array);
If the values can contain space, change the regexp to:
/(:\w+:)([^:]+)\s/g
This will match anything not containing : as the value, but not include the last space.
You can achieve the same result without using regex.
const stringVar = ":20:9077f1722efa3632 :12:700 :77E:xxx :27A:2/2 :21A:9077f1722efa3632 :27:1/2 :40A:IRREVOCABLE";
const result = stringVar
.split(' ')
.reduce((ret, current) => {
const pos = current.indexOf(':', 1);
ret[current.substring(0, pos + 1)] = current.substring(pos + 1);
return ret;
}, {});
console.log(result);
I have a string in javascript where there are a lot of duplicates. For example I have:
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double"
What can I do to delete duplicates and to get for example x="Int32,Double"?
With Set and Array.from this is pretty easy:
Array.from(new Set(x.split(','))).toString()
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double"
x = Array.from(new Set(x.split(','))).toString();
document.write(x);
If you have to support current browsers, you can split the array and then filter it
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double";
var arr = x.split(',');
x = arr.filter(function(value, index, self) {
return self.indexOf(value) === index;
}).join(',');
document.body.innerHTML = x;
Use new js syntax remove Dupicate from a string.
String.prototype.removeDuplicate = Function() {
const set = new Set(this.split(','))
return [...set].join(',')
}
x.removeDuplicate()
function myFunction(str) {
var result = "";
var freq = {};
for(i=0;i<str.length;i++){
let char = str[i];
if(freq[char]) {
freq[char]++;
} else {
freq[char] =1
result = result+char;
}
}
return result;
}
That is a more readable and better parameterized solution:
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double"
var removeDup = [...new Set(x.split(","))].join(",");
//result "Int32,Double"
Check This out -
removeDuplicates() function takes a string as an argument and then the string split function which is an inbuilt function splits it into an array of single characters. Then the arr2 array which is empty at beginning, a forEach loop checks for every element in the arr2 - if the arr2 has the element it will not push the character in it, otherwise it will push. So the final array returned is with unique elements. Finally we join the array with the join() method to make it a string.
const removeDuplicates = (str) => {
const arr = str.split("");
const arr2 = [];
arr.forEach((el, i) => {
if (!arr2.includes(el)) {
arr2.push(el);
}
});
return arr2.join("").replace(",", "").replace("", " ");
};
console.log(removeDuplicates( "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double"));
Its simple just remove duplicates in string using new Set and join them.
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double";
console.log([...new Set(x)].join(""));
function removeDups(s) {
let charArray = s.split("");
for (let i = 0; i < charArray.length; i++) {
for (let j = i + 1; j < charArray.length; j++)
if (charArray[i] == charArray[j]) {
charArray.splice(j, 1);
j--;
}
}
return charArray.join("");
}
console.log(removeDups("Int32,Int32,Int32,InInt32,Int32,Double,Double,Double"));
You can use Set()
const result = Array.from(new Set(x)).join('')
var x = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double"
const result = Array.from(new Set(x)).join('')
console.log(result)
you can use the replaceAll function:
let str = "/Courses/"
let newStr = str.replaceAll('/', '')
console.log(newStr) // result -> Courses
function removeDuplicate(x)
{
var a = x.split(',');
var x2 = [];
for (var i in a)
if(x2.indexOf(a[i]) == -1) x2.push(a[i])
return x2.join(',');
}
const str = "Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Int32,Double,Double,Double";
const usingSpread = [...str]
const duplicatesRemove = [...new Set(usingSpread)]
const string = duplicatesRemove.join("")
console.log("After removing duplicates: " + string)
STEPS
convert string to character array using spread operator
new Set will implicitly remove duplicate character
convert character array to string using join("") method
I want something like this:
"abcdab".search(/a/g) //return [0,4]
Is it possible?
You can use the RegExp#exec method several times:
var regex = /a/g;
var str = "abcdab";
var result = [];
var match;
while (match = regex.exec(str))
result.push(match.index);
alert(result); // => [0, 4]
Helper function:
function getMatchIndices(regex, str) {
var result = [];
var match;
regex = new RegExp(regex);
while (match = regex.exec(str))
result.push(match.index);
return result;
}
alert(getMatchIndices(/a/g, "abcdab"));
You could use / abuse the replace function:
var result = [];
"abcdab".replace(/(a)/g, function (a, b, index) {
result.push(index);
});
result; // [0, 4]
The arguments to the function are as follows:
function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%
If you only want to find simple characters, or character sequences, you can use indexOf [MDN]:
var haystack = "abcdab",
needle = "a"
index = -1,
result = [];
while((index = haystack.indexOf(needle, index + 1)) > -1) {
result.push(index);
}
You can get all match indexes like this:
var str = "abcdab";
var re = /a/g;
var matches;
var indexes = [];
while (matches = re.exec(str)) {
indexes.push(matches.index);
}
// indexes here contains all the matching index values
Working demo here: http://jsfiddle.net/jfriend00/r6JTJ/
A non-regex variety:
var str = "abcdabcdabcd",
char = 'a',
curr = 0,
positions = [];
while (str.length > curr) {
if (str[curr] == char) {
positions.push(curr);
}
curr++;
}
console.log(positions);
http://jsfiddle.net/userdude/HUm8d/
Another non-regex solution:
function indexesOf(str, word) {
const split = str.split(word)
let pointer = 0
let indexes = []
for(let part of split) {
pointer += part.length
indexes.push(pointer)
pointer += word.length
}
indexes.pop()
return indexes
}
console.log(indexesOf('Testing JavaScript, JavaScript is the Best, JavaScript is Ultimate', 'JavaScript'))
Based on #jfriend00 answer but tidied up:
const getAllIndices = (str, strToFind) => {
const regex = RegExp(strToFind, 'g')
const indices = []
let matches
while (matches = regex.exec(str)) indices.push(matches.index)
return indices
}
console.log(getAllIndices('hello there help me', 'hel'))
console.log(getAllIndices('hello there help me', 'help'))
console.log(getAllIndices('hello there help me', 'xxxx'))