C# 查找第一个大写字符的索引
作为一名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
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}")
);