Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查找第一个大写字符的索引_C#_String_Linq_Search - Fatal编程技术网

C# 查找第一个大写字符的索引

C# 查找第一个大写字符的索引,c#,string,linq,search,C#,String,Linq,Search,作为一名C语言新手,为了找出字符串中第一个大写字符的索引,我想出了一种方法 var pos = spam.IndexOf(spam.ToCharArray().First(s => String.Equals(s, char.ToUpper(s)))); 从功能上讲,代码运行得很好,只是我有两次遍历字符串的不适感,一次是查找字符,然后是索引。是否有可能使用LINQ一次性获得第一个大写字符的索引 C++中的等价方法将是类似于的 std::string::const_iterator it

作为一名C语言新手,为了找出字符串中第一个大写字符的索引,我想出了一种方法

var pos = spam.IndexOf(spam.ToCharArray().First(s => String.Equals(s, char.ToUpper(s))));
从功能上讲,代码运行得很好,只是我有两次遍历字符串的不适感,一次是查找字符,然后是索引。是否有可能使用LINQ一次性获得第一个大写字符的索引

C++中的等价方法将是类似于

std::string::const_iterator itL=find_if(spam.begin(), spam.end(),isupper);
等效的Python语法是

next(i for i,e in enumerate(spam) if e.isupper())
不需要LINQ:

int index = 0;
foreach(Char c in myString)
{
   if(Char.IsUpper(c)) break;
   index++;
}

// index now contains the index of the first upper case character
这可以很容易地转换为扩展方法,如@Tigran注释。

好吧,如果您只想在LINQ中实现,您可以尝试使用

(from ch in spam.ToArray() where Char.IsUpper(ch) 
         select spam.IndexOf(ch))
如果您对字符串运行此命令,请说

"string spam = "abcdeFgihjklmnopQrstuv";"
结果是:5,16


这将返回预期的结果

这是一个基于@Tigran的答案,但它将返回所有大写字母的索引,即使有重复:

from i in Enumerable.Range(0, searchText.Length - 1) 
      where Char.IsUpper(searchText.Chars[i]) select i

只是因为我经常发现人们不知道:

Select有一种方法可以获取索引以及要枚举的项。 即使它会稍微增加开销,您也可以这样做:

var objectsWithCharAndIndex = myString.Select((c,i)=>new {Char = c,Index = i});
那么,这只是一个行动的问题:

var firstCapitalIndex = objectsWithCharAndIndex.First(o => Char.IsUpper(o.Char)).Index;
或者全部归还

var allCapitalIndexes = objectsWithCharAndIndex.Where(o => Char.IsUpper(o.Char)).Select(o=>o.Index);
当然,如果需要同时使用char和索引,可以遍历对象

这只是普通的Linq语法,而不是Linq查询语法。

另一种可能:

string s = "0123aBc";
int rslt = -1;
var ch = s.FirstOrDefault(c => char.IsUpper(c));
if (ch != 0)
    rslt = s.IndexOf(ch);
如果你只关心英语:

char[] UpperCaseChars = new char[] 
{
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
    'Y', 'Z'
};
int rslt = s.IndexOfAny(UpperCaseChars);
这可能会比其他的执行速度快很多,如果我经常这样做的话,我会用它

另一种可能是使用正则表达式:

var match = Regex.Match(s, "\p{Lu}", RegexOptions.None);
int rslt = match.Success ? match.Index : -1;

这将匹配任何Unicode大写字符。如果您只需要英语,请将表达式更改为[A-Z]。

Linq并没有提供一种开箱即用的有效方法,但您可以扩展Linq以非常轻松地提供此功能

如果将此类添加到解决方案中:

internal static class EnumerableExtensions
{
    public static int IndexOfNth<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate, int skip = 0)
    {
        var index = 0;
        foreach (var value in enumerable)
        {
            if (predicate(value))
            {
                if (skip-- == 0)
                    return index;
            }
            index++;
        }
        return -1;
    }

    public static int IndexOfFirst<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
    {
        return enumerable.IndexOfNth(predicate);
    }
}
注意:如果字符串不包含任何大写字母,则索引超出范围,因此需要额外检查IndexOfFirst是否返回-1

通过此实现,您还可以找到第二个大写字母,如下所示:

var secondUpper = spam[spam.IndexOfNth(Char.IsUpper, 1)];
它适用于任何可枚举项,而不仅仅是字符的枚举

var indexOfFirstManager = employees.IndexOfFirst(employee => employee.IsManager);

或者只是一个扩展方法。LINQ很好,但使用时要小心,不仅仅是在任何地方。@Oded:谢谢你的回复。我知道这可以通过简单的迭代轻松完成。我试图弄清楚LINQ是否有合适的功能。当然,如果不存在,classic foreach会做得很好。@Abhijit-在LINQ中是可能的,但是查询需要跟踪索引等,这是一件麻烦事,你能麻烦你至少开导一下灰质吗?这样像我这样的新手就可以找到陷阱,避免这样的构造。@Abhijit-就是这样,我想不出一个好办法在LINQ做这件事。。。我也不想发布坏代码。6000的名声Novice@NikhilAgrawalC:这是发电机吗?例如,如果我首先对上面的表达式应用,它会继续计算整个字符串吗?同样对我来说,上面的生成器非常简单,但是你能给出一个避免使用上面构造的可读性/可维护性的原因吗?@Abhijit:我编辑了我的文章,并给出了一个例子。那么构造呢,它只是关于可读性,我非常清楚这通常是纯粹主观的,所以简单的foreach对我来说似乎更可读一点,在这种情况下,LINQ。这是一个选择的问题。选择你喜欢的。由于上面返回的是IEnumerable,我想知道的是上面的表达式是a还是a。在我的问题中,我有一个Python的例子,它应该阐明我的意图。@Abhijit:不,在这种情况下,您不能控制循环中的迭代行为,因为generator代表什么。这里查询一个数据,并对其进行迭代。如果你想这样做,你应该使用foreach和yield的组合。不过,你可以保存ToArray调用,因为string是一个IEnumerable。
var indexOfFirstManager = employees.IndexOfFirst(employee => employee.IsManager);
String.Concat(
  str.Select(c => Char.IsUpper(c) ? $" {c}" : $"{c}")
);