如何使用基于字符的正则表达式将值匹配到单独的可选组中



输入的3个示例:

"13-4h50m2s"
"13-4h2s"
"13-50m"

首选代码:

const [hours = 0, minutes = 0, seconds = 0] = input.match(some_regexp)

对于以下3个示例,需要输出{小时、分钟、秒}:

{hours: 4, minutes: 50, seconds: 2}
{hours: 4, minutes: 0,  seconds: 2}
{hours: 0, minutes: 50, seconds: 0}

Regex我试过了:/(d+)?[a-z](d+)?[a-z]?(d+)?[a-z]?/。但第二个例子不起作用。

编辑:输入可以预期按正确的顺序(h,m,s)进行排序。这些值是以字符串还是数字的形式存储也没关系。

编辑2:很抱歉更新太晚了,实际上输入的13-部分也可以忽略,但它没有太大区别,无论如何都可以很容易地进行调整。

这应该可以回答您的问题:

const labelMap = { h: 'hours', m: 'minutes', s: 'seconds' };
[
"13-4h50m2s",
"13-2s4h",
"13-50m"
].forEach((str) => {
let obj = { hours: 0, minutes: 0, seconds: 0 };
str.replace(/(d+)([hms])/g, (m, p1, p2) => {
obj[labelMap[p2]] = parseInt(p1, 10);
});
console.log(JSON.stringify(obj));
});

输出:

{"hours":4,"minutes":50,"seconds":2}
{"hours":4,"minutes":0,"seconds":2}
{"hours":0,"minutes":50,"seconds":0}

注:

  • labelMap从输入单元映射到所需的输出对象键
  • 使用一个没有返回的字符串替换,它只用于迭代我们想要的模式:/(d+)([hms])/g
  • 替换函数根据数字和单位组成对象

您可以匹配数字和后缀,然后使用Object.fromEntries将结果转换为对象。使用具有排列语法的对象初始化程序为未填充的属性获取0:

const parse = s =>
({h: 0, m: 0, s: 0, ...
Object.fromEntries(s.match(/d+[msh]/g).map(m => [m[m.length-1], parseInt(m)]))
});
let inputs = [
"13-4h50m2s",
"13-2s4h",
"13-50m"
];
console.log(inputs.map(parse));

注意:这会重复使用单个字母h、m、s作为属性名称。

所以我实际上得到了一个我满意的工作解决方案:

const inputs = [
'1h2m3s',
'4h5m',
'6m',
'7h8s',
'9m10s'
]
const re = /(?<hours>d+(?=h))?[hms]?(?<minutes>d+(?=m))?[hms]?(?<seconds>d+(?=s))?/
for (str of inputs) {
const match = re.exec(str)
const {hours = 0, minutes = 0, seconds = 0} = match.groups
console.log({hours,minutes,seconds})
}

字符串和数字是混合的,但这没关系,只要h、m、s的顺序正确,它就可以工作。

正则表达式

我使用了可选的命名捕获组,并对相应的时间单位进行了前瞻性处理,然后在两者之间使用了可选的[hms]字符集。

相关内容

最新更新