我的字符串输入如下所示:

const text = '<Jane>:flower: <Kate><john> :like: received:flower::flower:'

我需要编写一个函数,它将计算每个人有多少朵花.昵称总是以这样的模式放入标签中:<nickname>,它们不区分大小写.因此,每个nick都应该以小写形式保存.

解析nick后,程序应该搜索子字符串":flower:"并计算它被满足的次数.如果有一个以上的缺口,一个接一个,那么它们应该被链在一起.所以所有的":flower:"子字符串count,也就是跟在它们后面的子字符串,都应该被添加到每个nick中.

如果在文本中两次遇到相同的尼克,则将其后的花朵计数添加到结果对象中保存的计数中.

如果在一个刻痕链组中遇到相同的刻痕,例如: <John><John><John> :flower: <Kate>. 然后,每次遇到缺口时,它都会在这一连串缺口之后添加花的数量.所以,在这个例子中,Jogn得到了三朵花,而Kate没有得到,因为她在她的nick之后没有花.

但是,我只能使用:

  1. 正好一个for循环;
  2. 存储如下结果的一个对象: { jane: 1, kate: 2, john: 2 }

我不能使用数组、嵌套循环、原生JS方法(toLowerCase()除外)或正则表达式.有人能帮我这个忙吗?

我一直在思考如何在不使用数组的情况下将昵称"链接在一起".我有这样的代码,它只是返回一个对象,它包含所有的刻痕,文本中有.

function countFlowers(text) {
  const nickTag = "<>";
  const result = {};
  let isParsingNick = false;

  let currentNick = '';
  let nickTagIndex = 0;
  for (let i = 0; i < text.length; i++) {
    const current = text[i];

    if (!isParsingNick && current === nickTag[nickTagIndex]) {
      if (nickTagIndex === 0) {
        isParsingNick = true;
        currentNick = '';
      }
      nickTagIndex++;
    } else if (isParsingNick && current === nickTag[nickTagIndex]) {
      if (nickTagIndex === 1) {
        isParsingNick = false;
        result[currentNick] = 0;
        nickTagIndex = 0;
        continue;
      }
      nickTagIndex++;
    } else if (isParsingNick && current !== nickTag[nickTagIndex]) {
      currentNick += current.toLowerCase();
    }
  }

  return result;
}

const text = '<Jane>:flower: <Kate><john> :like: received:flower::flower:'
console.log(countFlowers(text))

输入和结果的更多示例:

1. const text = '<Jane>:flower: <kate>:like:<John> :like: 
received:flower::flower:'
// {
//     jane: 1,
//     kate: 2,
//     john: 2
// }
2. const text = '<Jane>:flower: <kate>:flower: :flower: :flower: <John> :like: received:flower::flower:'
// {
//     jane: 1,
//     kate: 3,
//     john: 2,
// }
3. const text = '<Jane>:flower: <kate>:flower flower: flower:<John> :like: received:flower::flower:'
//because between kate and john there are no valid :flower: then they 
are grouped together
// {
//     jane: 1,
//     kate: 2,
//     john: 2,
// }
4. const text = '<Jane>:flower: <kate>:like:<John> :like: 
received:flower::flower: <Jane> alsdaksdjhsa <Jane> :flower: :flower:'
// {
//     jane: 5,
//     kate: 2,
//     john: 2
// }
5. const text = '<Jane>:flower: <kate><Kim><Jacob><Emily> :like: received:flower::flower:  <Kim><Jacob><Jane>'
// {
//     jane: 1
//     kate:2
//     kim:2
//     jacob:2
//     emily:2
// }
 6. const text = ':flower: :flower: <Jane>:flower: <kate><John> :like: received:flower::flower: '
//if there are flowers not after nickname - they are skipped
// {
//     jane: 1,
//     kate: 2,
//     john: 2,
// }

推荐答案

我不认为你需要isParsingNick,因为这对应于一个非零的nickTagIndex.

您可以应用相同的系统来匹配具有以下规格的:flower::

  • 仅当我们遇到至少一个nick时,才应匹配该字符串
  • 如果匹配是部分的并且被中断,那么索引(flowerIndex)应该被重置为0.
  • 如果检测到完全匹配,则增加花数

为了允许多个nick获得同一朵花的计数,您可以使用nicks的链接列表(因为不允许使用数组).然后,当遇到新的刻度(或输入结束)并且花计数不是零时,将该花计数添加到链表中的所有刻度,然后清空链表并重置花计数.

结果是这样的:

function countFlowers(text) {
    const nickTag = "<>";
    const flower = ":flower:";
    const result = {};
    let currentNicks = null; // This will be a linked list (as no arrays allowed)

    let nickTagIndex = 0;
    let flowerIndex = 0;
    let flowerCount = 0;
    for (let token of text + nickTag) { // Add empty nick so to flush the remaining flowers
        if (token === nickTag[nickTagIndex]) {
            if (!nickTagIndex) {
                if (flowerCount) { // Flush flowers
                    // Assign the flowers to the nicks in the linked list
                    while (currentNicks) {
                        result[currentNicks.nick] = (result[currentNicks.nick] ?? 0) + flowerCount;
                        currentNicks = currentNicks.next;
                    }
                    flowerCount = 0;
                }
                currentNicks = { nick: "", next: currentNicks };
            }
            nickTagIndex = (nickTagIndex + 1) % nickTag.length;
        } else if (nickTagIndex) {
            currentNicks.nick += token.toLowerCase();
        } else if (currentNicks && token === flower[flowerIndex]) {
            flowerIndex = (flowerIndex + 1) % flower.length;
            if (!flowerIndex) {
                flowerCount++;
            }
        } else {
            flowerIndex = 0;
        }
    }

    return result;
}


const text = '<Jane>:flower: <Kate><john> :like: received:flower::flower:'
const result = countFlowers(text);
console.log(result);

增编

如果您希望避免使用链表,那么可以向后迭代输入.这样,在到达关联的刻痕之前,您就已经知道要指定的花数,然后可以在识别刻痕后立即指定这些花朵.

以下是为实现该 idea 而更新的上述脚本.我还在这里包含了您的测试用例:

function countFlowers(text) {
    const nickTag = "><"; // reversed!
    const flower = ":rewolf:";  // reversed!
    const result = {};
    let currentNick = "";

    let nickTagIndex = 0;
    let flowerIndex = 0;
    let flowerCount = 0;
    let addFlowerCount = 0;
    for (let i = text.length - 1; i >= 0; i--) { // Traverse in reverse
        let token = text[i];
        if (token === nickTag[nickTagIndex]) {
            if (flowerCount) {
                addFlowerCount = flowerCount;
                flowerCount = 0;
            }
            nickTagIndex = (nickTagIndex + 1) % nickTag.length;
            if (!nickTagIndex) {
                result[currentNick] = (result[currentNick] ?? 0) + addFlowerCount;
                currentNick = "";
            }
        } else if (nickTagIndex) {
            currentNick = token.toLowerCase() + currentNick; // prepend!
        } else if (token === flower[flowerIndex]) {
            flowerIndex = (flowerIndex + 1) % flower.length;
            if (!flowerIndex) {
                flowerCount++;
            }
        } else {
            flowerIndex = 0;
        }
    }

    return result;
}

// Your test cases:
const texts = [
    '<Jane>:flower: <kate>:like:<John> :like: received:flower::flower:',
    '<Jane>:flower: <kate>:flower: :flower: :flower: <John> :like: received:flower::flower:',
    '<Jane>:flower: <kate>:flower flower: flower:<John> :like: received:flower::flower:',
    '<Jane>:flower: <kate>:like:<John> :like: received:flower::flower: <Jane> alsdaksdjhsa <Jane> :flower: :flower:',
    '<Jane>:flower: <kate><Kim><Jacob><Emily> :like: received:flower::flower:  <Kim><Jacob><Jane>',
    ':flower: :flower: <Jane>:flower: <kate><John> :like: received:flower::flower: ',
];
for (const text of texts) {
    const result = countFlowers(text);
    console.log(result);
}

注意,现在输出对象中属性的顺序可能遵循不同的顺序,因为这些属性是按插入顺序输出的(除非它们是indexes--这是依赖普通对象中键的顺序可能有风险的原因).

Javascript相关问答推荐

如何在JavaScript中在文本内容中添加新行

如何获取转换字节的所有8位?

如何在Angular中插入动态组件

按下同意按钮与 puppeteer 师

在vercel throws上部署带有gunjs的sveltekit应用无法找到模块./' lib/文本编码'

浮动Div的淡出模糊效果

处理时间和字符串时MySQL表中显示的日期无效

在286之后恢复轮询

Regex结果包含额外的match/group,只带一个返回

如何 for each 输入动态设置输入变更值

Vaadin定制组件-保持对javascrip变量的访问

如何限制显示在分页中的可见页面的数量

Phaser3 preFX addGlow不支持zoom

在JavaScript中,有没有一种方法可以迭代字符串的词法标记?

未捕获的不变违规:即使在使用DndProvider之后也应使用拖放上下文

在ChartJS中使用spanGaps时,是否获取空值的坐标?

我如何才能获得价值观察家&对象&S的价值?

如何将值从后端传递到前端

MUI-TABLE:MUI表组件中交替行的不同 colored颜色 不起作用

鼠标进入,每秒将图像大小减小5%