我正在寻找运营商的字符串。我需要字符串
中的实际运算符及其索引例如:x>10&y>=10
运营商
>
&
>=
=
所以我需要像
这样的结果> 1
& 4
>= 6
所以我写了这样的代码
string substr= "x>10&y>=10";
List<string> substringList = new List<string>{">", "&", ">=", "="};
var orderedOccurances = substringList
.Where((substr) => str.IndexOf(substr, StringComparison.Ordinal) >= 0)
.Select((substr, inx) => new
{ substr, inx = str.IndexOf(substr, StringComparison.Ordinal) })
.OrderBy(x => x.inx).ToList();
但是我得到了这样的结果(显然)
> 1
& 4
> 6
= 7
我可以使用for循环进行搜索并覆盖此错误场景。但我喜欢linq短手代码。无论如何我可以使用lambdas / linq覆盖错误条件吗?
答案 0 :(得分:1)
所以基本上你想要的是扫描你的序列中的字符'lt'','&gt;','='和'&amp;',如果发现其中任何一个,请记住索引和找到的字符,如果'&LT;'或'&gt;'发现你想知道'='是否在它之后,如果是,那么下一次搜索应该在'='之后开始。
请注意,您未使用&=
或==
指定所需内容。
每当你必须扫描字符串以获得某种语法时,至少考虑使用正则表达式总是明智的。
根据上面的规范,如果您发现以下任何内容,则需要匹配的正则表达式:
代码很简单:
using System.Text.RegularExpressions;
string expression = ...;
var regex = new RegularExpression("&|<=|>=|[<>][^=]");
var matches = regex.Matches(expression);
对象matches
是Match
个对象的数组。每个match
对象都有属性Index
,Length
和Value
;正是你想要的属性。
foreach (var match in matches)
{
Console.WriteLine($"Match {match.Value} found"
+ " at index {match.Index} with length {match.Length}");
}
正则表达式中的竖线|
表示OR; [ ]
表示括号中的任意字符; [^ ]
表示不是括号之间的任何字符。
如果&
或<=
或>=
或<>
中没有=
后面的任何字符,则会找到匹配。
如果你还想找到&amp; =和==,那么你的规则表达会更容易:
代码:
var regex = new Regex("[<>&=]|[<>&=][^=]");
一个优秀的在线正则表达式测试程序,您可以在其中检查正则表达式can be found here。这也显示了找到的匹配项以及正则表达式语法的描述。
答案 1 :(得分:1)
这是更通用的替代方案:
string str = "x>10&y>=10";
var result = Regex.Matches(str, @">=|>|&|=").Cast<Match>()
.Select(m => new { s = m.Value, i = m.Index }).ToList();
结果:
> 1
& 4
>= 6
如果字符串中没有任何其他运算符,则或更短一些:
var d = Regex.Matches(str, @"\W+").Cast<Match>().ToDictionary(m => m.Index, m => m.Value);
答案 2 :(得分:0)
好吧,如果您一直在使用LINQ,您可以执行以下操作:
public static IEnumerable<(int Index, string Substring)> GetAllIndicees(this string str, IEnumerable<string> subtrings)
{
IEnumerable<(int Index, string Substring)> GetAllIndicees(string substring)
{
if (substring.Length > str.Length)
return Enumerable.Empty<(int, string)>();
if (substring.Length == str.Length)
return Enumerable.Repeat((0, str), 1);
return from start in Enumerable.Range(0, str.Length - substring.Length + 1)
where str.Substring(start, substring.Length).Equals(substring)
select (start, substring);
}
var alloperators = subtrings.SelectMany(s => GetAllIndicees(s));
return alloperators.Where(o => !alloperators.Except(new[] { o })
.Any(other => o.Index >= other.Index &&
o.Index < other.Index + other.Substring.Length &&
other.Substring.Contains(o.Substring)));
}
使用c#7语法,因为这些代码更简洁,更易读,但可以轻松翻译到以前的版本。
现在,如果你这样做:
var substr = "x>10&y>=10";
var operators = new HashSet<string>(new[] { ">", "&", ">=", "=" });
Console.WriteLine(string.Join(", ", filteredOperators.Select(o => $"[{o.Operator}: {o.Index}]")));
您将获得预期的结果:
[>: 1], [&: 4], [>=: 6]
这是&#34;更好&#34;比使用其他工具?我不太确定。