Reputation: 2838
I have this string (called currentExecution.variables):
{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}
and I need to convert it into a Map so that I can work with the entries, but I'm having a hard time doing this. I've tried, following this answer, to transform it into a key-value set of pairs. First I've replaced = with : and { or } with white space, then splitted it according to the answer:
newString.split(/,(?=[^,]+:)/).map(s => s.split(': '));
but I do not get the proper result, and I'm stuck without the Map. What's missing? Or is there a better/faster way to do this?
Upvotes: 0
Views: 7948
Reputation: 11
I have this string (called stats):
active_total: 1087
cumulative: 1
trace_total: 10
which is not even in JSON format.
This is the solution that I am trying:
let keyValuePairs = stats
.split(/\s*\n\s*/) //split with optional spaces around the comma
.map(chunk => chunk.split(": ")); //split key=value
const map = new Map(keyValuePairs);
console.log(map.get("sessions_active_total"));
console.log(map.get("cumulative"));
But it is throwing compilation error at this line:
const map = new Map(keyValuePairs);
Error message:
error TS2769: No overload matches this call.
Overload 1 of 3, '(iterable: Iterable<readonly [unknown, unknown]>): Map<unknown, unknown>', gave the following error.
Argument of type 'string[][]' is not assignable to parameter of type 'Iterable<readonly [unknown, unknown]>'.
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
Type 'IteratorResult<string[], any>' is not assignable to type 'IteratorResult<readonly [unknown, unknown], any>'.
Type 'IteratorYieldResult<string[]>' is not assignable to type 'IteratorResult<readonly [unknown, unknown], any>'.
Type 'IteratorYieldResult<string[]>' is not assignable to type 'IteratorYieldResult<readonly [unknown, unknown]>'.
Type 'string[]' is not assignable to type 'readonly [unknown, unknown]'.
Target requires 2 element(s) but source may have fewer.
Overload 2 of 3, '(entries?: readonly (readonly [unknown, unknown])[]): Map<unknown, unknown>', gave the following error.
Argument of type 'string[][]' is not assignable to parameter of type 'readonly (readonly [unknown, unknown])[]'.
Type 'string[]' is not assignable to type 'readonly [unknown, unknown]'.
58 const map = new Map(keyValuePairs);
Upvotes: -1
Reputation: 5853
You can capture the key and value pairs in a capturing group shown in this regex.
Based on that you can go ahead and reduce its value to a Map.
const currentExecutionVariable = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
const pattern = /([A-Za-z0-9]+)\=([A-Za-z0-9]+)/g;
const matches = currentExecutionVariable.match(pattern);
const currentExecutionMap = matches.reduce((acc, curr) => {
const [key, value] = curr.split('=');
if (!acc.has(key)) {
acc.set(key, value);
}
return acc;
}, new Map());
for (const [key, value] of currentExecutionMap.entries()) {
console.log (`${key}: ${value}`);
}
Update
Using the captured groups:
const currentExecutionVariable = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
const pattern = /([A-Za-z0-9]+)\=([A-Za-z0-9]+)/g;
let currentExecutionMap = new Map();
let capturedGroup;
while ((capturedGroup = pattern.exec(currentExecutionVariable))) {
// 1st captured group is the key of the map
const key = capturedGroup[1];
// 2nd captured group is the value of the map
const value = capturedGroup[2];
if (!currentExecutionMap.has(key)) {
currentExecutionMap.set(key, value);
}
}
for (const [key, value] of currentExecutionMap.entries()) {
console.log(`${key}: ${value}`);
}
Upvotes: 2
Reputation: 13195
You can work without regexps too, but you have to understand the basic concept of that first you split along the ,
s, and then along the =
s:
var data = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
var pairs = data.substring(1, data.length - 1).split(", "); // step 1, split using commas
var obj = pairs.reduce(function(acc, cur) {
var pair = cur.split("="); // step 2, split using =
acc[pair[0].trim()] = pair[1].trim();
return acc;
}, {});
console.log(obj);
Upvotes: 3
Reputation: 29041
You can do the following
{
and }
characters from the start and end the string. Do not use replace
in case there are any occurrences inside it.let string = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
let keyValuePairs = string.slice(1, -1) //remove first and last character
.split(/\s*,\s*/) //split with optional spaces around the comma
.map(chunk => chunk.split("=")); //split key=value
const map = new Map(keyValuePairs);
console.log(map.get("executionid"));
console.log(map.get("timeout"));
Upvotes: 5