我有一个字符串,需要最终得到一个对象来计算每个名字的所有苹果,我的努力是为他们拿走的每个苹果获得单独的匹配
在 <@Viktor><@Kate>took:apple::apple: 部分中,我想要获得两个匹配项而不是 1 个,如果有更多像 <@Viktor><@Kate>took:apple::apple::apple::apple:
这样的苹果,则需要更多匹配项const message = 'I had :apple::apple::apple::apple: :apple:<@Viktor><@Kate>took:apple::apple: and later <@viktor> took again:apple:but not <@kate>';
const result {
viktor: 3,
kate: 2
}
用这个来处理问题,但是没有被面试官接受,因为我后来使用了join&split。任务是仅使用正则表达式来解决这个问题。
function countGifts(text) {
let result = {}
let names = ['viktor', 'kate']
names.forEach(name=>{
let regex = new RegExp(`(${name}).*?(:apple:)+`, "gi")
result[name] = text.match(regex).join('').split(':apple:').length-1
})
return result
}
console.log(
countGifts(message)
);
我是正则表达式的新手,并且希望获得具有复杂示例的文章的替代解决方案和提示,因为我发现的所有内容都非常简单
我假设如果多个名称标签彼此后面可能带有一些分隔文本,但不是
:apple:
,那么它们都会得到后面的苹果。我还将假设,如果名称标签在此类列表中重复,则重复项将被忽略。所以 <@Victor><@Victor> :apple:
会将一个苹果分配给 Victor,而不是两个。
这是一种方法:
function countGifts(text) {
const result = {};
let isCollecting = false;
const names = new Set; // Those that will get apples
for (const [_, name] of text.matchAll(/:apple:|<@(\w+)>/g)) {
if (name === undefined) { // Add apple
isCollecting = false;
for (const key of names) {
result[key] = (result[key] || 0) + 1;
}
} else {
if (!isCollecting) names.clear();
isCollecting = true;
names.add(name.toLowerCase());
}
}
return result;
}
const message = 'I had :apple::apple::apple::apple: :apple:<@Viktor><@Kate>took:apple::apple: and later <@viktor> took again:apple:but not <@kate>';
const result = countGifts(message);
console.log(result);