#c# #linq
#c# #linq
Вопрос:
У меня есть функция, которая сравнивает две строки и сообщает о первом отличном символе:
public static int Diff(this string str1, string str2)
{
try
{
if (str1 == null || str2 == null)
return 0;
int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
return index;
}
catch (Exception)
{
return 0;
}
}
итак, вся магия здесь:
int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
допустим, у нас есть две строки:
ВВОД,1,1,0,0,0,0,0,0,0,0,0,0
ВВОД,?,?,1,?,?,?,?,?,?,?,?,?
01234567890
итак, учитывая все символы, первый отличается? итак, ответ равен 6 (начиная с 0). Это работает правильно.
Теперь я хотел бы представить ? в качестве подстановочного символа, который поэтому должен быть пропущен, и поэтому ответ должен быть 10 (начиная с 0).
Я не знаю, как изменить приведенный выше код в выражении linq, чтобы сделать это. Я пытался int index = str1.Zip(str2, (c1, c2) => c1 == c2 amp;amp; c2!='?').TakeWhile(b => b).Count();
, но это ничего не меняет и всегда сообщает 6 вместо 9.
Я хотел бы придерживаться linq вместо прохождения (более простого) цикла for Спасибо
Комментарии:
1.
c1 == c2 || c2 == '?'
Ответ №1:
Вам нужно, чтобы подстановочный знак учитывался как дополнительное возможное true
условие. Поэтому вам нужно использовать ИЛИ ||
вместо И amp;amp;
:
Не:
int index = str1.Zip(str2, (c1, c2) => c1 == c2 amp;amp; c2 != '?').TakeWhile(b => b).Count();
Вместо:
int index = str1.Zip(str2, (c1, c2) => c1 == c2 || c2 == '?').TakeWhile(b => b).Count();
Вы можете добавить дополнительный ||
к выражению, если вы также хотите игнорировать подстановочные знаки в первом вводе.
Ответ №2:
Я думаю, вам просто нужно немного изменить логическое условие.
Если условие, используемое в Zip
, когда-либо ложно, мы прекращаем поиск там. Мы должны прекратить поиск только тогда, когда два символа не совпадают и один из них не является подстановочным знаком.
Итак, условие должно быть:
!(c1 != c2 amp;amp; (c1 != '?' || c2 != '?'))
Очевидно, что это можно упростить, используя законы Деморгана:
c1 == c2 || c1 != '?' || c2 != '?'
Поэтому строка становится:
index = str1.Zip(str2, (c1, c2) => c1 == c2 || c1 != '?' || c2 != '?').TakeWhile(b => b).Count();
Ответ №3:
используя linq, поиграйте здесь.
var index = c1.Zip(c2, (a, b) => new { a, b })
.Select((p, i) => new { p.a, p.b, i })
.Where(p => p.b != wildcard)
.FirstOrDefault(p => p.a != p.b)?.i;
Ответ №4:
Вот полностью протестированное решение :
string input1 = "1,1,0,0,0,0,0,0,0,0,0,0";
string input2 = "u003F,u003F,1,u003F,u003F,u003F,u003F,u003F,u003F,u003F,u003F,u003F";
int results = input1.Select((x, i) => new { chr = x, index = i }).Where(x => (x.chr != input2[x.index]) amp;amp; (x.chr != 'u003F') amp;amp; (input2[x.index] != 'u003F')).Min(x => x.index);