获取 C# 字符串中第一个非空白字符的索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12695501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:08:19  来源:igfitidea点击:

Get Index of First non-Whitespace Character in C# String

c#

提问by Eric J.

Is there a means to get the index of the first non-whitespace character in a string (or more generally, the index of the first character matching a condition) in C# without writing my own looping code?

有没有办法在 C# 中获取字符串中第一个非空白字符的索引(或更一般地说,匹配条件的第一个字符的索引)而无需编写我自己的循环代码?

EDIT

编辑

By "writing my own looping code", I really meant that I'm looking for a compact expression that solves the problem without cluttering the logic I'm working on.

通过“编写我自己的循环代码”,我的真正意思是我正在寻找一种紧凑的表达式来解决问题而不会使我正在处理的逻辑混乱。

I apologize for any confusion on that point.

对于在这一点上的任何混淆,我深表歉意。

采纳答案by Douglas

I like to define my own extension method for returning the index of the first element that satisfies a custom predicate in a sequence.

我喜欢定义自己的扩展方法,用于返回满足序列中自定义谓词的第一个元素的索引。

/// <summary>
/// Returns the index of the first element in the sequence 
/// that satisfies a condition.
/// </summary>
/// <typeparam name="TSource">
/// The type of the elements of <paramref name="source"/>.
/// </typeparam>
/// <param name="source">
/// An <see cref="IEnumerable{T}"/> that contains
/// the elements to apply the predicate to.
/// </param>
/// <param name="predicate">
/// A function to test each element for a condition.
/// </param>
/// <returns>
/// The zero-based index position of the first element of <paramref name="source"/>
/// for which <paramref name="predicate"/> returns <see langword="true"/>;
/// or -1 if <paramref name="source"/> is empty
/// or no element satisfies the condition.
/// </returns>
public static int IndexOf<TSource>(this IEnumerable<TSource> source, 
    Func<TSource, bool> predicate)
{
    int i = 0;

    foreach (TSource element in source)
    {
        if (predicate(element))
            return i;

        i++;
    }

    return -1;
}

You could then use LINQ to address your original problem:

然后您可以使用 LINQ 来解决您的原始问题:

string str = "   Hello World";
int i = str.IndexOf<char>(c => !char.IsWhiteSpace(c));

回答by Samy Arous

You can use the String.IndexOfAnyfunction which returns the first occurrence any character in a specified array of Unicode characters.

您可以使用String.IndexOfAny函数,该函数返回指定 Unicode 字符数组中第一次出现的任何字符。

Alternatively, you can use the String.TrimStartfunction which remove all white space characters from the beginning of the string. The index of the first non-white space character is the difference between the length of the original string and the trimmed one.

或者,您可以使用String.TrimStart函数从字符串的开头删除所有空格字符。第一个非空白字符的索引是原始字符串与修剪后的字符串长度之差。

You can even pick a set of characters to trim :)

您甚至可以选择一组字符进行修剪:)

Basically, if you are looking for a limited set of chars (let's say digits) you should go with the first method.

基本上,如果您正在寻找一组有限的字符(比如数字),您应该使用第一种方法。

If you are trying to ignore a limited set of characters (like white spaces) you should go with the second method.

如果您试图忽略一组有限的字符(如空格),您应该使用第二种方法。

A Last method would be to use the Linqmethods:

最后一种方法是使用Linq方法:

string s = "        qsdmlkqmlsdkm";
Console.WriteLine(s.TrimStart());
Console.WriteLine(s.Length - s.TrimStart().Length);
Console.WriteLine(s.FirstOrDefault(c => !Char.IsWhiteSpace(c)));
Console.WriteLine(s.IndexOf(s.FirstOrDefault(c => !Char.IsWhiteSpace(c))));

Output:

输出:

qsdmlkqmlsdkm
8
q
8

回答by Damian Schenkelman

You can trim, get the first character and use IndexOf.

您可以修剪、获取第一个字符并使用 IndexOf。

回答by Tim S.

var match = Regex.Match(" \t test  ", @"\S"); // \S means all characters that are not whitespace
if (match.Success)
{
    int index = match.Index;
    //do something with index
}
else
{
    //there were no non-whitespace characters, handle appropriately
}

If you'll be doing this often, for performance reasons you should cache the compiled Regexfor this pattern, e.g.:

如果您经常这样做,出于性能原因,您应该缓存Regex为此模式编译的内容,例如:

static readonly Regex nonWhitespace = new Regex(@"\S");

Then use it like:

然后像这样使用它:

nonWhitespace.Match(" \t test  ");

回答by Henk Holterman

A stringis of course an IEnumerable<char>so you can use Linq:

Astring当然是 anIEnumerable<char>所以你可以使用 Linq:

int offset = someString.TakeWhile(c => char.IsWhiteSpace(c)).Count();

回答by hmakled

Yes you can try this:

是的,你可以试试这个:

string stg = "   xyz";
int indx = (stg.Length - stg.Trim().Length);  

回答by Aaron Anodide

Something is going to be looping somewhere. For full control over what is and isn't whitespace you could use linq to objects to do your loop:

有些东西会在某处循环。为了完全控制什么是空白和不是空白,您可以使用 linq to objects 来执行循环:

int index = Array.FindIndex(
               s.ToCharArray(), 
               x => !(new [] { '\t', '\r', '\n', ' '}.Any(c => c == x)));

回答by Gene S

string s= "   \t  Test";
Array.FindIndex(s.ToCharArray(), x => !char.IsWhiteSpace(x));

returns 6

返回 6

To add a condition just do ...

要添加条件,只需执行...

Array.FindIndex(s.ToCharArray(), x => !char.IsWhiteSpace(x) && your condition);

回答by Gene S

Since there were several solutions here I decided to do some performance tests to see how each performs. Decided to share these results for those interested...

由于这里有几个解决方案,我决定进行一些性能测试,看看每个解决方案的表现如何。决定将这些结果分享给感兴趣的人……

    int iterations = 1000000;
    int result = 0;
    string s= "   \t  Test";

    System.Diagnostics.Stopwatch watch = new Stopwatch();

    // Convert to char array and use FindIndex
    watch.Start();
    for (int i = 0; i < iterations; i++)
        result = Array.FindIndex(s.ToCharArray(), x => !char.IsWhiteSpace(x)); 
    watch.Stop();
    Console.WriteLine("Convert to char array and use FindIndex: " + watch.ElapsedMilliseconds);

    // Trim spaces and get index of first character
    watch.Restart();
    for (int i = 0; i < iterations; i++)
        result = s.IndexOf(s.TrimStart().Substring(0,1));
    watch.Stop();
    Console.WriteLine("Trim spaces and get index of first character: " + watch.ElapsedMilliseconds);

    // Use extension method
    watch.Restart();
    for (int i = 0; i < iterations; i++)
        result = s.IndexOf<char>(c => !char.IsWhiteSpace(c));
    watch.Stop();
    Console.WriteLine("Use extension method: " + watch.ElapsedMilliseconds);

    // Loop
    watch.Restart();
    for (int i = 0; i < iterations; i++)
    {   
        result = 0;
        foreach (char c in s)
        {
            if (!char.IsWhiteSpace(c))
                break;
            result++;
        }
    }
    watch.Stop();
    Console.WriteLine("Loop: " + watch.ElapsedMilliseconds);

Results are in milliseconds....

结果以毫秒为单位......

Where s = " \t Test"
Convert to char array and use FindIndex: 154
Trim spaces and get index of first character: 189
Use extension method: 234
Loop: 146

where s = " \t Test"
转换为char数组并使用FindIndex:154
修剪空格并获取第一个字符的索引:189
使用扩展方法:234
循环:146

Where s = "Test"
Convert to char array and use FindIndex: 39
Trim spaces and get index of first character: 155
Use extension method: 57
Loop: 15

where s = "Test"
转换为char数组并使用FindIndex:39
修剪空格并获取第一个字符的索引:155
使用扩展方法:57
循环:15

Where s = (1000 character string with no spaces)
Convert to char array and use FindIndex: 506
Trim spaces and get index of first character: 534
Use extension method: 51
Loop: 15

where s = (1000 string with no space)
转换为char数组并使用FindIndex:506
修剪空格并获取第一个字符的索引:534
使用扩展方法:51
循环:15

Where s = (1000 character string that starts with " \t Test")
Convert to char array and use FindIndex: 609
Trim spaces and get index of first character: 1103
Use extension method: 226
Loop: 146

where s = (1000 string that starts with " \t Test")
转换为char数组并使用FindIndex:609
修剪空格并获取第一个字符的索引:1103
使用扩展方法:226
循环:146

Draw your own conclusions but my conclusion is to use whichever one you like best because the performance differences is insignificant in real world scenerios.

得出你自己的结论,但我的结论是使用你最喜欢的那个,因为在现实世界的场景中性能差异是微不足道的。

回答by Sunil Purushothaman

There is a very simple solution

有一个非常简单的解决方案

string test = "    hello world";
int pos = test.ToList<char>().FindIndex(x => char.IsWhiteSpace(x) == false);

pos will be 4

pos 将是 4

you can have more complex conditions like:

您可以有更复杂的条件,例如:

pos = test.ToList<char>().FindIndex((x) =>
                {
                    if (x == 's') //Your complex conditions go here
                        return true;
                    else 
                        return false;
                }
            );