每三个单词分割字符串

3

我有一个问题。我需要像这样分割每个字符串: 例如: “经济驱动力无限制”

我需要一个包含子字符串的数组,例如: “经济驱动力无” “驱动力无限制”

目前我有以下代码:

            List<string> myStrings = new List<string>();
        foreach(var text in INPUT_TEXT) //here is Economic drive without restrictions
        {
            myStrings.DefaultIfEmpty();
            var textSplitted = text.Split(new char[] { ' ' });
            int j = 0;
            foreach(var textSplit in textSplitted)
            {

                int i = 0 + j;
                string threeWords = "";
                while(i != 3 + j)
                {
                    if (i >= textSplitted.Count()) break;
                    threeWords = threeWords + " " + textSplitted[i];
                    i++;
                }
                myStrings.Add(threeWords);
                j++;
            }
        }

每次循环都需要将j增加3。 - stark
1
同时,您需要检查textSplitted的结尾。 - stark
4个回答

6
您可以使用以下的LINQ查询:
string text = "Economic drive without restrictions";
string[] words = text.Split();
List<string> myStrings = words
    .Where((word, index) => index + 3 <= words.Length)
    .Select((word, index) => String.Join(" ", words.Skip(index).Take(3)))
    .ToList();

因为其他人评论说最好显示循环版本,因为OP正在学习这种语言,所以这里有一个完全不使用LINQ的版本:

List<string> myStrings = new List<string>();
for (int index = 0; index + 3 <= words.Length; index++)
{ 
    string[] slice = new string[3];
    Array.Copy(words, index, slice, 0, 3);
    myStrings.Add(String.Join(" ", slice));
}

1
我想知道为什么人们总是用Linq查询来回答这样的问题。我认为这些人只是在学习编程,那么复制和粘贴他们不理解的Linq查询有什么好处呢?他们还是会在基本操作上挣扎。 - Bgl86
@Bgl86:这是主观的,但我认为LINQ比“基本操作”如显式循环更容易理解和理解。那么为什么不学习如何使用LINQ编写可读性强且易于维护的代码呢?将OP的方法与这个简洁的查询进行比较。 - Tim Schmelter
我知道LINQ。但是我认为当你学习编程时,理解循环和条件等基础知识是必不可少的。那么如果没有LINQ可用,OP如何使用Javascript解决相同的任务呢? - Bgl86
@MatthewWatson:收到,我编辑了我的答案,提供了一个非 Linq 版本。 - Tim Schmelter
1
@Bgl86:明白了,我编辑了我的答案,提供了一个非 LINQ 版本。但是它不是 JavaScript,并且任务不是避免所有 .NET 方法。 - Tim Schmelter

1

我尝试提供一个简单的解决方案,希望您能更好地理解它。

    List<string> myStrings = new List<string>();

    string input = "Economic drive without restrictions";

    var allWords = input.Split(new char[] {' '});

    for (int i = 0; i < allWords.Length - 2; i++)
    {
        var textSplitted = allWords.Skip(i).Take(3);
        string threeString = string.Join(" ", textSplitted);
        myStrings.Add(threeString);
    }

    foreach (var myString in myStrings)
    {
        Console.WriteLine(myString);
    }

方法Take(n)来自Linq。它获取给定数组的前n个元素。例如,如果您有一个数组a,b,c,d,e,那么Take(3)将给您一个新数组a,b,c
方法Skip(n)来自Linq。通过跳过前n个元素,它会给你一个新数组。给定数组a,b,c,d,e,那么Skip(1)将返回b,c,d,e。正如你所看到的,它跳过了第一个元素。
现在,有了这两种方法,您可以按每3个元素移动数组并获取您想要的单词。

1
小细节:SkipTake不会给你一个数组,它们使用延迟执行,基本上它们什么都不会给你,只是查询。你需要执行它,例如使用ToArrayToList、在foreach中或隐藏在string.Join中。 - Tim Schmelter
@TimSchmelter 感谢您提醒我。是的,它不是一个数组。但是在这里没有必要将它们转换为数组,因为这些方法以及 Join 方法都可以使用 IEnumerable。 - M.kazem Akhgary

1

仅供比较,这里有另外一种不使用Linq的解决方案:

string[] words = INPUT_TEXT.Split();
List<string> myStrings = new List<string>();

for (int i = 0; i < words.Length - 2; ++i)
    myStrings.Add(string.Join(" ", words[i], words[i+1], words[i+2]));

或者使用 ArraySegment<string>:
string[] words = INPUT_TEXT.Split();
List<string> myStrings = new List<string>();

for (int i = 0; i < words.Length - 2; ++i)
    myStrings.Add(string.Join(" ", new ArraySegment<string>(words, i, 3)));

++ params[] 重载的 string.JoinArraySegment<> 的使用案例非常不错。 - Tim Schmelter

0

我会使用这里描述的方法之一;例如以下方法,它按3个元素一组进行操作。

var groups = myStrings.Select((p, index) => new {p,index})
                      .GroupBy(a =>a.index/3);

警告,它不是最节省内存的,如果你开始解析大字符串,它可能会崩溃。尝试并观察。

然后你只需要处理最后一个元素。如果它少于3个字符串,请从左侧填充。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接