【问题标题】:Typescript convert string to Map打字稿将字符串转换为地图
【发布时间】:2019-05-14 09:57:14
【问题描述】:

我有这个字符串(称为 currentExecution.variables):

{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}

并且我需要将其转换为 Map 以便我可以处理这些条目,但我很难做到这一点。我已经尝试按照this answer 将其转换为一组键值对。首先,我将 = 替换为 : 并将 { 或 } 替换为空格,然后根据答案将其拆分:

newString.split(/,(?=[^,]+:)/).map(s => s.split(': '));

但我没有得到正确的结果,而且我在没有地图的情况下被困住了。少了什么东西?还是有更好/更快的方法来做到这一点?

【问题讨论】:

  • 假设第一部分有效:你有'=' 可以拆分,而不是': '(尤其是没有空格)。
  • 为什么?如果我将 = 替换为 :,我将无法拆分 =
  • 我说过我已经用 : 替换了我的 =。因此生成的字符串将与原始字符串相同,但使用 : 而不是 =。然后在这个字符串上进行拆分。
  • @Dseaster 你说得对,我错过了那部分。
  • @Dseaster Map 在Map object 中,或者 Map 只是一个对象,就像解析后的 json 会产生什么?

标签: javascript arrays string split


【解决方案1】:

您可以执行以下操作

  1. 从字符串的开头和结尾删除{} 字符。不要使用replace,以防其中有任何事件。
  2. 将结果拆分为形成键值对的每个离散块。
  3. 将它们拆分为实际的键和值
  4. 结果可以很容易地转换为 Map,因为构造函数 takes an array where each item is an array with two items 会将结果转换为第一项是键,第二项是值的映射:

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"));

【讨论】:

  • 谢谢,我就是这个意思。此解决方案是否适用于 String 中随机数量的 key=value 对?
  • @Dseaster 是的,它适用于任意数量的键值对。如果值包含逗号 , 或包含等号 =,您可能会遇到问题 - 在这些情况下,拆分可能会出错。
【解决方案2】:

你也可以不使用正则表达式,但你必须先了解它的基本概念,然后沿着,s 拆分,然后沿着=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);

【讨论】:

  • 对我来说是对的,即使它没有返回地图。不知道为什么它被认为是错误的。
  • 是的,我认为有人只是连续投票否决了这里的所有内容。没错 - 我实际上是要添加一个使用对象的部分,但你打败了我。
  • @Dseaster 是的,我认为是那个人删除了他的答案。
  • 显然用户开始对我过去的所有问题投反对票。你还记得他的用户名吗?我再也找不到他了。
  • @Dseaster 有一种机制可能会在以后恢复它:meta.stackexchange.com/questions/126829/… - 所以明天检查你的历史记录。
【解决方案3】:

您可以在this regex 所示的捕获组中捕获键值对。

基于此,您可以继续将其值降低为 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}`);
}

更新

使用捕获的组:

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}`);
}

【讨论】:

  • 您不需要在正则表达式中转义= - 该字符没有特殊含义。此外,.reduce 也不是绝对需要的,因为您只需执行 new Map([["key1", "value1"], ["key2", "value2"]]) 即可填充地图。尽管如此,这些都是次要的 - 很好的解决方案。我建议的实际改进是使用正则表达式中的捕获组 - 执行pattern.exec(currentExecutionVaruable) 将提供捕获的键和值,您是否不需要拆分结果。 while(result = pattern.exec(currentExecutionVaruable)) map.set(result[1], result[2])`
  • @VLAZ 我认为=的拆分是不必要的,我会更新我的答案
【解决方案4】:

我有这个字符串(称为 stats):

active_total: 1087
cumulative: 1
trace_total: 10

甚至不是 JSON 格式。

This 是我正在尝试的解决方案:

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"));

但它在这一行抛出编译错误:

const map = new Map(keyValuePairs);

错误信息:

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);

【讨论】:

  • 这属于问题的范畴,将其发布为对别人问题的回答是完全错误的。提出一个新问题以引起对您问题的更多关注,其他人会尽力回答。干杯,欢迎来到 SO!
猜你喜欢
  • 1970-01-01
  • 2019-10-30
  • 2017-02-11
  • 2019-11-12
  • 1970-01-01
  • 2019-06-05
  • 2016-10-21
  • 2018-06-07
  • 2016-09-10
相关资源
最近更新 更多