每个人。我很抱歉我的英语不好。我的任务很简单:逐个字符读取文件,并计算每个字母。语言并不重要。起初,我使用了一个包含所有受限字符的字符串:
"1234567890`~!@#$%^&*()_+-=!№;%:?*(){}[];:|',./<>? "
这是一个愚蠢的想法,所以我决定使用:
!Char.IsLetter(data[i].letter)
data.RemoveAt(i);
没用。即使是下面的也不起作用(好吧,我没想到)
if(Char.IsDigit(data[i].letter) || Char.IsSymbol(data[i].letter)||Char.IsControl(data[i].letter) ||Char.IsNumber(data[i].letter) ||Char.IsPunctuation(data[i].letter) ||Char.IsSeparator(data[i].letter) ||Char.IsSymbol(data[i].letter) ||Char.IsWhiteSpace(data[i].letter))
data.RemoveAt(i);
它仍然会让一些数字和合成词溜走。最烦人的是"\r",我无法摆脱它。我需要一个可以判断字符是否是字母的解决方案。我是新手,所以越简单越好。提前感谢!
只需计算对象数组中的字母数:
data.Count(x => char.IsLetter(x.letter));
这使用LINQ Count
方法,并为letter
字段调用char.IsLetter
,以确定是否应将每个字符添加到计数中。
示例:(只有一个字符串而不是对象数组)
var data = "ABC_123_r_%$#";
var count = data.Count(char.IsLetter);
Console.WriteLine(count);
将按预期打印3。
请注意,如果文件顶部还没有using System.Linq;
,则必须将其添加到文件顶部。
如果您的data
实际上是List<Data>()
,并且如果您的代码看起来像这样:
for (int i = 0; i < data.Count; i++)
if (!Char.IsLetter(data[i].letter))
data.RemoveAt(i);
使用
public class Data
{
public char letter { get; set; }
}
那么您就有了一个错误——您将跳过对删除的字母后面的每个字母的测试,因为对RemoveAtt(i)
的调用将使所有后续列表项的索引减少1。相反,您应该使用RemoveAll()
:
data.RemoveAll(d => !char.IsLetter(d.letter));
您的问题是在迭代期间修改集合
using System.Collections.Generic;
using System.Linq;
namespace Example
{
class Program
{
static void Main(string[] args)
{
List<char> data = "1234567890".ToList();
//This does not remove all the element!!!
for (int i = 0; i < data.Count; i++)
data.RemoveAt(i);
}
}
}
你需要这个
static void Main(string[] args)
{
List<char> data = "1234567890".ToList();
List<char> toDelete = new List<char>();
for (int i = 0; i < data.Count; i++)
toDelete.Add(data[i]);
for (int i = 0; i < toDelete.Count; i++)
data.Remove(toDelete[i]);
}
或者行数较少(如您所见,IsLetter运行良好,它与没有问题\r\n)
List<char> data = (Environment.NewLine + "1234567890").ToList();
data = data.Where(l => char.IsLetter(l)).ToList();
使用正则表达式代替
Regex.IsMatch(input, @"^[a-zA-Z]+$");
或更简单的
Regex.IsMatch(input, "[a-zA-Z]");