简体   繁体   English

如何在按钮之间平均分割字符串字符?

[英]How to split characters of string equally between buttons?

I have an array of string elements of various words. 我有各种单词的字符串元素数组。 I need the characters of each word be split equally into the text component of 3 buttons. 我需要将每个单词的字符平均分为3个按钮的文本部分。 For example, the array could hold the elements "maybe", "his", "car" . 例如,数组可以包含元素"maybe", "his", "car" In each game one of these words will be pulled from the array and its characters divided into the 3 buttons. 在每个游戏中,这些单词中的一个将从数组中拉出,其角色分为3个按钮。 For example, button 1 will have "ma" , button 2 will have "yb" and button 3 "e" (for the word maybe). 例如,按钮1将具有"ma" ,按钮2将具有"yb" ,按钮3将具有"e" (可能是单词)。 I then hide the text element of one button for the user to drag and drop the correct missing letter(s) into the space. 然后,我隐藏了一个按钮的文本元素,以供用户将正确的丢失字母拖放到该空格中。 The purpose of the game is to help children learn to spell. 游戏的目的是帮助孩子学习拼写。 Does anyone know how I could go about dividing the characters equally into the 3 buttons? 有谁知道我该如何将字符平均分成3个按钮?

Here's a function that would split the word into the amount of segments you want. 这是一个功能,可以将单词拆分为所需的段数。 You can then iterate over that list to set each segment to a button.Text. 然后,您可以遍历该列表以将每个段设置为button.Text。

public List<string> SplitInSegments(string word, int segments)
{
    int wordLength = word.Length;

    // The remainder tells us how many segments will get an extra letter
    int remainder = wordLength % segments;

    // The base length of a segment
    // This is a floor division, because we're dividing ints.
    // So 5 / 3 = 1
    int segmentLength = wordLength / segments;

    var result = new List<string>();
    int startIndex = 0;
    for (int i = 0; i < segments; i++)
    {
        // This segment may get an extra letter, if its index is smaller then the remainder
        int currentSegmentLength = segmentLength + (i < remainder ? 1 : 0);

        string currentSegment = word.Substring(startIndex, currentSegmentLength);

        // Set the startindex for the next segment.
        startIndex += currentSegmentLength;

        result.Add(currentSegment);
    }

    return result;
}

usage: 用法:

// returns ["ma", "yb", "e"]
var segments = SplitInSegments("maybe", 3);

Edit 编辑

I like the fact that this is for teaching children. 我喜欢这样的事实,那就是教孩子们。 So here comes. 所以来了。 Regarding your question on splitting the string based on specific letter sequences: After you've split the string using regex, you will have an array of strings. 关于根据特定字母序列拆分字符串的问题:使用regex拆分字符串后,将有一个字符串数组。 Then determine the amount of items in the splitted string and concatenate or split further based on the number of segments: 然后确定分割后的字符串中的项目数量,并根据段数进一步串联或分割:

// sequences to split on first
static readonly string[] splitSequences = {
    "el",
    "ol",
    "bo"
};

static readonly string regexDelimiters = string.Join('|', splitSequences.Select(s => "(" + s + ")"));

// Method to split on sequences
public static List<string> SplitOnSequences(string word)
{
    return Regex.Split(word, regexDelimiters).Where(s => !string.IsNullOrEmpty(s)).ToList();
}

public static List<string> SplitInSegments(string word, int segments)
{
    int wordLength = word.Length;

    // The remainder tells us how many segments will get an extra letter
    int remainder = wordLength % segments;

    // The base length of a segment
    // This is a floor division, because we're dividing ints.
    // So 5 / 3 = 1
    int segmentLength = wordLength / segments;

    var result = new List<string>();
    int startIndex = 0;
    for (int i = 0; i < segments; i++)
    {
        // This segment may get an extra letter, if its index is smaller then the remainder
        int currentSegmentLength = segmentLength + (i < remainder ? 1 : 0);

        string currentSegment = word.Substring(startIndex, currentSegmentLength);

        // Set the startindex for the next segment.
        startIndex += currentSegmentLength;

        result.Add(currentSegment);
    }

    return result;
}

// Splitword will now always return 3 segments
public static List<string> SplitWord(string word)
{
    if (word == null)
    {
        throw new ArgumentNullException(nameof(word));
    }

    if (word.Length < 3)
    {
        throw new ArgumentException("Word must be at least 3 characters long", nameof(word));
    }

    var splitted = SplitOnSequences(word);

    var result = new List<string>();
    if (splitted.Count == 1)
    {
        // If the result is not splitted, just split it evenly.
        result = SplitInSegments(word, 3);
    }
    else if (splitted.Count == 2)
    {
        // If we've got 2 segments, split the shortest segment again.
        if (splitted[1].Length > splitted[0].Length
            && !splitSequences.Contains(splitted[1]))
        {
            result.Add(splitted[0]);
            result.AddRange(SplitInSegments(splitted[1], 2));
        }
        else
        {
            result.AddRange(SplitInSegments(splitted[0], 2));
            result.Add(splitted[1]);
        }
    }
    else // splitted.Count >= 3
    { 
        // 3 segments is good.
        result = splitted;

        // More than 3 segments, combine some together.
        while (result.Count > 3)
        {
            // Find the shortest combination of two segments
            int shortestComboCount = int.MaxValue;
            int shortestComboIndex = 0;
            for (int i = 0; i < result.Count - 1; i++)
            {
                int currentComboCount = result[i].Length + result[i + 1].Length;
                if (currentComboCount < shortestComboCount)
                {
                    shortestComboCount = currentComboCount;
                    shortestComboIndex = i;
                }
            }

            // Combine the shortest segments and replace in the result.
            string combo = result[shortestComboIndex] + result[shortestComboIndex + 1];
            result.RemoveAt(shortestComboIndex + 1);
            result[shortestComboIndex] = combo;
        }
    }

    return result;
}

Now when you call the code: 现在,当您调用代码时:

// always returns three segments.
var splitted = SplitWord(word);

Here is another approach. 这是另一种方法。

First make sure that the word can be divided by the desired segments (add a dummy space if necessary) , then use a Linq statement to get your parts and when adding the result trim away the dummy characters. 首先,请确保可以将单词除以所需的句段(如有必要,请添加一个虚拟空格),然后使用Linq语句获取所需的部分,并在添加结果时修剪掉虚拟字符。

public static string[] SplitInSegments(string word, int segments)
{
    while(word.Length %  segments != 0) { word+=" ";}
    var result = new List<string>();
    for(int x=0; x < word.Count(); x += word.Length / segments)
    result.Add((new string(word.Skip(x).Take(word.Length / segments).ToArray()).Trim()));
    return result.ToArray();
}

You can split your string into a list and generate buttons based on your list. 您可以将字符串拆分为一个列表,然后根据列表生成按钮。 The logic for splitting the word into a string list would be something similar to this: 将单词拆分为字符串列表的逻辑类似于以下内容:

string test = "maybe"; 字符串测试=“也许”; List list = new List(); 列表列表=新的List();

    int i = 0, len = 2;
    while(i <= test.Length)
    {
        int lastIndex = test.Length - 1;
        list.Add(test.Substring(i, i + len > lastIndex? (i + len) - test.Length : len));
        i += len;       
    }

HTH HTH

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

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