简体   繁体   English

通过 C# 中的预定义索引从字符串中删除多个“单词”?

[英]Remove multiple "words" from a string by predefined indexes in C#?

I'm trying to create my first chat bot for Twitch and I've ran into some issues with the emotes Twitch uses.我正在尝试为 Twitch 创建我的第一个聊天机器人,但我遇到了 Twitch 使用的表情的一些问题。

I need to be able to delete several emotes (emotes on Twitch are just words) from a string.我需要能够从字符串中删除几个表情(Twitch 上的表情只是单词)。
I don't know what the word is, but I know where in the string the word is located at, the starting index and length that is.我不知道这个词是什么,但我知道这个词在字符串中的位置,起始索引和长度。

For example, the message: Hello HeyGuys how are you? WutFace WutFace例如,消息: Hello HeyGuys how are you? WutFace WutFace Hello HeyGuys how are you? WutFace WutFace produces the following on Twitch: Hello HeyGuys how are you? WutFace WutFace在 Twitch 上生成以下内容:

在此处输入图片说明

Using tmi.js I can fetch this message, including the emotes in the message and send them to my C# program.使用tmi.js我可以获取这条消息,包括消息中的表情并将它们发送到我的 C# 程序。
The message I receive in C# from tmi.js looks like this:我在 C# 中从 tmi.js 收到的消息如下所示:

{ '28087': [ '27-33', '35-41' ], '30259': [ '6-12' ] } {'28087':['27-33','35-41'],'30259':['6-12']}

Where "28087" and "30259" are the IDs of the emotes and 27-33, 35-41 and 6-12 are the position of the emotes within the message itself.其中“28087”和“30259”是表情的 ID,27-33、35-41 和 6-12 是表情在消息本身中的位置。

How can I delete all those words/emotes from my string with the predefined start and stop positions of each word/emote?如何使用每个单词/表情的预定义开始和停止位置从我的字符串中删除所有这些单词/表情?

A non successful attempt by me:我的一次不成功的尝试:

dynamic json = JsonConvert.DeserializeObject(emotes); // { '28087': [ '27-33', '35-41' ], '30259': [ '6-12' ] }
int prevLength = 0;
foreach (var a in json)
{
    foreach (var b in a)
    {
        for (int i = 0; i < b.Count; i++)
        {
            string range = b[i];
            int start = Convert.ToInt32(range.Split('-')[0]);
            int end = Convert.ToInt32(range.Split('-')[1]);
            int length = end - start;
            length = length + 1;
            if (prevLength != 0)
            {
                start = start - prevLength;
            }
            prevLength = prevLength + length;
            message = message.Remove(start, length);
        }
    }
}

The above code can delete multiple emotes/words from the string as long as the emote/word is the same.上面的代码可以从字符串中删除多个表情/单词,只要表情/单词相同即可。 Mixing emotes/words does not work.混合表情/单词不起作用。

First of all, I'd encourage you to get rid of that dynamic .首先,我鼓励你摆脱这种dynamic Not only because you completely lose type safety, but also because it makes it harder to understand what you're doing.不仅因为你完全失去了类型安全,还因为它让你更难理解你在做什么。 You can have a much nicer structure with just:你可以有一个更好的结构:

var ranges = JsonConvert
    .DeserializeObject<Dictionary<string, string[]>>(emotes)
    // Get the strings in each list, the Key doesn't matter here
    .SelectMany(x => x.Value)
    // And transform the strings into objects like { int Start; int End; }
    .Select(x => 
    { 
        var splitted = x.Split('-'); 

        return new 
        { 
            Start = int.Parse(splitted[0]), 
            End = int.Parse(splitted[1]) 
        }; 
    });

Now, you don't need 3 loops, you don't need to worry about splitting, parsing nor anything else.现在,您不需要 3 个循环,您不需要担心拆分、解析或其他任何事情。 You just need to work on removing those indexes from your string:您只需要从字符串中删除这些索引:

foreach (var range in ranges)
{
    // TODO: remove range from message using range.Start and range.End
}

Already much simpler!已经简单多了! Now, as for actually removing the emotes, you need to carefully consider the indexes of the rest of the emotes once you remove one.现在,至于实际删除表情,您需要在删除后仔细考虑其余表情的索引。
You could take each random emote and deal with the start and end index in message after each removal, but that's error prone and overall just too complex.您可以使用每个随机表情并在每次删除后处理message的开始和结束索引,但这很容易出错,而且总体上太复杂了。
There's a much simpler way to do this, and it's by starting from the last emote and working your way up to the first, and achieving this is only:有一种更简单的方法可以做到这一点,它是从最后一个表情开始,一直到第一个,实现这一点只是:

var ranges = JsonConvert
    // ... existing code
    .OrderByDescending(x => x.End);

So now you have all the ranges ordered by their end position, allowing you to get rid of them quite easily:因此,现在您拥有按结束位置排序的所有范围,让您可以轻松摆脱它们:

foreach (var range in ranges)
{
    message = message.Remove(range.Start, range.End - range.Start + 1);
}

Take a look at this in action: https://dotnetfiddle.net/QkktG3看看这个在行动: https : //dotnetfiddle.net/QkktG3

Hello HeyGuys how are you? WutFace WutFace
Hello HeyGuys how are you? WutFace 
Hello HeyGuys how are you?  
Hello  how are you?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM