Вы можете преобразовать буквы в шаблон и использовать Regex
:
var letters = "gaoaf";
var pattern = String.Join(".*",letters.AsEnumerable());
var hasletters = Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase);
Для тех, кто без необходимости избегает .*
, вы также можете решить эту проблему с помощью LINQ:
var ans = letters.Aggregate(0, (p, c) => p >= 0 ? s.IndexOf(c.ToString(), p, StringComparison.InvariantCultureIgnoreCase) : p) != -1;
Если возможно иметь повторяющиеся соседние буквы, вам нужно немного усложнить решение LINQ:
var ans = letters.Aggregate(0, (p, c) => {
if (p >= 0) {
var newp = s.IndexOf(c.ToString(), p, StringComparison.InvariantCultureIgnoreCase);
return newp >= 0 ? newp+1 : newp;
}
else
return p;
}) != -1;
Учитывая (некрасивые) махинации, необходимые для в основном завершения Aggregate
рано, и учитывая (некрасиво)и неэффективный) синтаксис, необходимый для использования встроенного вызова анонимного выражения, чтобы избавиться от временного newp
, я создал несколько расширений, чтобы помочь, Aggregate
, которые могут завершаться досрочно:
public static TAccum AggregateWhile<TAccum, T>(this IEnumerable<T> src, TAccum seed, Func<TAccum, T, TAccum> accumFn, Predicate<TAccum> whileFn) {
using (var e = src.GetEnumerator()) {
if (!e.MoveNext())
throw new Exception("At least one element required by AggregateWhile");
var ans = accumFn(seed, e.Current);
while (whileFn(ans) && e.MoveNext())
ans = accumFn(ans, e.Current);
return ans;
}
}
Теперь вы можетерешить проблему довольно легко:
var ans2 = letters.AggregateWhile(-1,
(p, c) => s.IndexOf(c.ToString(), p+1, StringComparison.InvariantCultureIgnoreCase),
p => p >= 0
) != -1;