Reputation: 27
I have the following string
Name=(Last, First), Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX
and I would like to split them into the following to build a dictionary
Name: "(Last, First)"
Age: "(31 year, 6 months, 3 day)"
Height: " 6.1 ft"
...
I came across this post and tried to tweak it but can get it work with keys with/out "()". Here is the code or from this link. Would appreciate your help and feel free to suggest easier or alternative way.
txt="Name=(Last, First), Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX"
//var r = /.+?=.+?(?=(\([^)]+\),)|(.=)|$)/g;
//var r = /.+?=.+?(?=(=(.*),)|$)/g;
var r = /.+?=.+?(?=(\),)|(\d\b,)|$)/g;
var obj = txt.match(r).reduce(function(obj, match) {
var keyValue = match.split("=");
obj[keyValue[0].replace(/,\s/g, '')] = keyValue[1];
return obj;
}, {});
console.log(obj);
Upvotes: 1
Views: 55
Reputation: 370679
To match the properties and values, you can use:
(\w+)\s*=\s*(\([^)]+\)|[^,]+)
(\w+)
- Match and capture the property (one or more word characters)\s*=\s*
- Followed by optional spaces, a =
, and more optional spaces(\([^)]+\)|[^,]+)
- Match and capture either:
\([^)]+\)
- A (
, followed by non-)
characters, followed by )
, OR[^,]+
- Non-comma charactersconst str = 'Name=(Last, First), Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX';
const obj = {};
for (const [, prop, val] of str.matchAll(/(\w+)\s*=\s*(\([^)]+\)|[^,]+)/g)) {
obj[prop] = val;
}
console.log(obj);
If the input keys may contain spaces as well, match anything but a =
:
const str = 'Employee Name=(Last, First), Person Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX';
const obj = {};
for (const [, prop, val] of str.matchAll(/(\w[^=]+)\s*=\s*(\([^)]+\)|[^,]+)/g)) {
obj[prop] = val;
}
console.log(obj);
If you can't use matchAll
, then iterate over the matches manually with exec
:
const str = 'Name=(Last, First), Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX';
const obj = {};
const pattern = /(\w+)\s*=\s*(\([^)]+\)|[^,]+)/g;
let match;
while (match = pattern.exec(str)) {
const [, prop, val] = match;
obj[prop] = val;
}
console.log(obj);
Upvotes: 1
Reputation: 520948
Here is one way, using a smart lookahead to split conditionally on only the correct commas:
var txt = "Name=(Last, First), Age=(31 year, 6 months, 3 day), Height= 6.1 ft, Employment=None, Email Address =/NA/, Mobile=XXXX"
var map = {};
var parts = txt.split(/,\s*(?![^(]*\))/);
parts.forEach(function (item, index) {
map[item.split(/=/)[0]] = item.split(/=/)[1];
});
console.log(map);
The regex used for splitting requires an explanation:
,\s* match comma with optional whitespace
(?![^(]*\)) assert that we cannot lookahead and see a closing ) without
first seeing an opening (
The lookahead condition prevents matching commas which happen to be inside (...)
terms. Then, once we have the array of terms, we iterate and build the dictionary you want, splitting each term on =
to find the key and value.
Upvotes: 1