【问题标题】:Javascript, split a string in 4 pieces, and leave the rest as one big pieceJavascript,将一个字符串分成 4 部分,其余部分保留为一大块
【发布时间】:2017-01-04 05:16:25
【问题描述】:

我正在为某事构建一个 Javascript 聊天机器人,但遇到了一个问题:
我使用string.split() 来标记我的输入,如下所示:
tokens = message.split(" ");

现在我的问题是我需要 4 个令牌来发出命令,以及 1 个令牌来发送消息。 当我这样做时: !finbot msg testuser 12345 Hello sir, this is a test message

这些是我得到的令牌: ["!finbot", "msg", "testuser", "12345", "Hello", "sir,", "this", "is", "a", "test", "message"]

但是,我怎样才能使它变成这样: ["!finbot", "msg", "testuser", "12345", "Hello sir, this is a test message"]

我想要这样的原因是因为第一个令牌(token[0])是调用,第二个(token[1])是命令,第三个(token[2])是用户,第四个(@ 987654329@) 是密码(因为它是受密码保护的消息……只是为了好玩),第五个 (token[4]) 是实际消息。
现在,它只会发送Hello,因为我只使用第 5 个令牌。
我不能像message = token[4] + token[5]; 这样的原因是因为消息并不总是正好是 3 个单词,或者不完全是 4 个单词等。

我希望我提供了足够的信息来帮助我。 如果你们知道答案(或知道更好的方法),请告诉我。

谢谢!

【问题讨论】:

    标签: javascript arrays tokenize


    【解决方案1】:

    使用String.splitlimit参数:

    tokens = message.split(" ", 4);
    

    从那里,您只需要从字符串中获取消息。将this answer 用于其nthIndex() 函数,您可以获得第4 次出现的空格字符的索引,并取其后的任何内容。

    var message = message.substring(nthIndex(message, ' ', 4))
    

    或者,如果您需要它在您的 tokens 数组中:

    tokens[4] = message.substring(nthIndex(message, ' ', 4))
    

    【讨论】:

    • 感谢您的回复,不幸的是我现在得到的token是:["!finbot", "msg", "testuser", "12345"]
    • 我现在已经这样做了:使用tokens[4] = message.substring(nthIndex(message, ' ', 4)); 但是,我得到了错误:nthIndex is not defined
    • @FinlayRoelofs - 您需要使用我链接到的答案中定义的函数...
    【解决方案2】:

    我可能会像你一样先获取字符串,然后对其进行标记:

    const myInput = string.split(" "):
    

    如果您使用的是 JS ES6,您应该能够执行以下操作:

    const [call, command, userName, password, ...messageTokens] = myInput;
    const message = messageTokens.join(" ");
    

    但是,如果您无权访问扩展运算符,您可以这样做(只是更冗长):

    const call = myInput.shift();
    const command = myInput.shift();
    const userName = myInput.shift();
    const password = myInput.shift();
    const message = myInput.join(" ");
    

    如果您再次需要它们作为数组,现在您可以加入这些部分:

    const output = [call, command, userName, password, message];
    

    【讨论】:

    • Firefox 45.3.0 是否支持 ES6?
    • 这是一个很好的问题,你可以自己谷歌一下? 但是,大多数在生产中使用 ES6 的人都在使用像 Babel 这样的工具进行编译。
    • 谢谢,我会调查的。从来不知道 ES6...一直认为 Javascript 只是...好吧... Javascript...
    • 不是最近!该语言正在发生很大的变化,尤其是最近几年。随时获得新功能!更多信息:babeljs.io/docs/learn-es2015
    • 非常有趣...我会调查的! (并尝试理解它)
    【解决方案3】:

    如果你可以使用 es6,你可以这样做:

    let  [c1, c2, c3, c4, ...rest] = input.split (" ");
    let msg = rest.join (" ");
    

    【讨论】:

    • Firefox 45.3.0 是否支持 ES6?
    • 特别需要解构支持。如果你愿意,你应该使用 babel 进行编译。
    【解决方案4】:

    您可以恢复为正则表达式,因为您将格式定义为“4 个非空格标记,以空格分隔,后跟消息”:

    function tokenize(msg) {
        return (/^(\S+) (\S+) (\S+) (\S+) (.*)$/.exec(msg) || []).slice(1, 6);
    }
    

    如果您的 msg 实际上与规范不匹配,这可能会导致返回空数组的不良行为。如果不可接受,请删除 ... || [] 并进行相应处理。代币数量也固定为 4 + 所需消息。对于更通用的方法,您可以:

    function tokenizer(msg, nTokens) {
        var token = /(\S+)\s*/g, tokens = [], match;
    
        while (nTokens && (match = token.exec(msg))) {
            tokens.push(match[1]);
            nTokens -= 1; // or nTokens--, whichever is your style
        }
    
        if (nTokens) {
            // exec() returned null, could not match enough tokens
            throw new Error('EOL when reading tokens');
        }
    
        tokens.push(msg.slice(token.lastIndex));
        return tokens;
    }
    

    这使用了 Javascript 中正则表达式对象的global 功能来重复测试相同的字符串,并使用lastIndex 属性在最后一个匹配的标记之后切片。

    给定

    var msg = '!finbot msg testuser 12345 Hello sir, this is a test message';
    

    然后

    > tokenizer(msg, 4)
    [ '!finbot',
      'msg',
      'testuser',
      '12345',
      'Hello sir, this is a test message' ]
    > tokenizer(msg, 3)
    [ '!finbot',
      'msg',
      'testuser',
      '12345 Hello sir, this is a test message' ]
    > tokenizer(msg, 2)
    [ '!finbot',
      'msg',
      'testuser 12345 Hello sir, this is a test message' ]
    

    请注意,空字符串将始终附加到返回的数组中,即使给定的消息字符串仅包含标记:

    > tokenizer('asdf', 1)
    [ 'asdf', '' ]  // An empty "message" at the end
    

    【讨论】:

    • 还有一个问题,如果我想使用较少数量的代币怎么办?比如让我们说总共3个令牌。所以 1 个命令是 5 个令牌,另一个命令是 3 个。
    • 用更通用的解决方案更新了答案。
    • 您好,很抱歉再次打扰您,但我一直在将我的机器人重写为 Node.JS 并对其进行了一些更新,但是,它杀死了标记器......现在,我的数组通过标记器运行它后得到的是空的。唯一改变的是!finbot 参数(它在代码的前面被剥离了)。所以数组现在只是["msg", "testuser", "12345", "Hello", "sir,", "this", "is", "a", "test", "message"] 我已经尝试了所有想到的东西,但我无法自己修复它。
    • 听起来您正在尝试将数组作为参数传递给函数。如果为真,那么很明显它不会起作用。它是用来分割字符串的。另一方面,它不应该返回一个空数组,而是失败。
    • 啊,是的,我明白了:) 我现在将整个字符串传递给它,它可以工作了!谢谢!现在我可以因为其他原因面对桌面:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2021-07-04
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    相关资源
    最近更新 更多