#c# #string #string-comparison
#c# #строка #сравнение строк
Вопрос:
В C #, как мне сравнить символы в двух строках.
Например, допустим, у меня есть эти две строки
«bc3231dsc» и «bc3462dsc»
Как мне программно определить, что строки
начинаются с «bc3» и заканчиваются «dsc»?
Таким образом, заданными будут две переменные:
var1 = "bc3231dsc";
var2 = "bc3462dsc";
После сравнения каждого символа из var1 в var2 я бы хотел, чтобы результат был:
leftMatch = "bc3";
center1 = "231";
center2 = "462";
rightMatch = "dsc";
Условия:
1. Строки всегда будут иметь длину 9 символов.
2. Строки не чувствительны к регистру.
Комментарии:
1. Каким должен быть ваш вывод? общий префикс и постфикс или что-то еще?
2. Вы пытаетесь сделать это в целом (итак, пять двух строк, сколько у них общих начальных и конечных символов) или только для этих двух строк?
3. Нужна дополнительная информация: всегда ли строки имеют одинаковую длину? Вас интересуют только совпадения с префиксом / постфиксом, или abc и bbb должны «совпадать» со средним символом «b»? Имеет ли значение корпус?
4. Строки всегда имеют одинаковую длину. Регистр не имеет значения.
Ответ №1:
Класс string имеет 2 метода (StartsWith и Endwith ), которые вы можете использовать.
Комментарии:
1. Как вы сравниваете две строки «bc3231dsc» и «bc3462dsc» друг с другом?
2. Я думаю, что это упускает главное: он не знает , что строки начинаются и заканчиваются одними и теми же символами (или какими могут быть эти символы).)
3. C N — пожалуйста, покажите пример того, что у вас не работает, поскольку не совсем ясно, сколько указаний вам нужно. Также, если это домашнее задание, пожалуйста, отметьте как таковое (тег — домашнее задание).
4. dlve прав. Я бы изначально не знал, с чего изначально будут начинаться или заканчиваться две строки. Я хочу сравнить две строки и посмотреть, какие символы у них общие с начала и конца.
Ответ №2:
После прочтения вашего вопроса и уже заданных ответов я думаю, что отсутствуют некоторые ограничения, которые, возможно, очевидны для вас, но не для сообщества. Но, может быть, мы можем сделать небольшую догадку:
- У вас будет куча пар строк, которые следует сравнить.
- Две строки в каждой паре имеют одинаковую длину, или вас интересует только сравнение символов, прочитанных одновременно слева направо.
- Получите какое-то перечисление, которое сообщает мне, где начинается каждый блок и какой он длины.
В связи с тем, что строка представляет собой всего лишь перечисление символов, вы можете использовать LINQ здесь, чтобы получить представление о совпадающих символах, подобных этому:
private IEnumerable<bool> CommonChars(string first, string second)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
var charsToCompare = first.Zip(second, (LeftChar, RightChar) => new { LeftChar, RightChar });
var matchingChars = charsToCompare.Select(pair => pair.LeftChar == pair.RightChar);
return matchingChars;
}
С этим мы можем продолжить и теперь выяснить, как долго длится каждый блок последовательных флагов true и false с помощью этого метода:
private IEnumerable<Tuple<int, int>> Pack(IEnumerable<bool> source)
{
if (source == null)
throw new ArgumentNullException("source");
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
bool current = iterator.Current;
int index = 0;
int length = 1;
while (iterator.MoveNext())
{
if(current != iterator.Current)
{
yield return Tuple.Create(index, length);
index = length;
length = 0;
}
current = iterator.Current;
length ;
}
yield return Tuple.Create(index, length);
}
}
В настоящее время я не знаю, существует ли уже существующая функция LINQ, которая обеспечивает ту же функциональность. Насколько я уже прочитал, это должно быть возможно с SelectMany()
помощью (потому что теоретически вы можете выполнить любую задачу LINQ с помощью этого метода), но в качестве реализации adhoc вышеприведенное было проще (для меня).
Затем эти функции можно было бы использовать примерно так:
var firstString = "bc3231dsc";
var secondString = "bc3462dsc";
var commonChars = CommonChars(firstString, secondString);
var packs = Pack(commonChars);
foreach (var item in packs)
{
Console.WriteLine("Left side: " firstString.Substring(item.Item1, item.Item2));
Console.WriteLine("Right side: " secondString.Substring(item.Item1, item.Item2));
Console.WriteLine();
}
Что бы вы тогда дали этому результату:
Левая сторона: bc3 Правая сторона: bc3
Левая сторона: 231 Правая сторона: 462
Левая сторона: dsc Правая сторона: dsc
Самым большим недостатком является то, что в некотором роде использование Tuple
cause приводит к уродливым именам свойств Item1
, Item2
которые далеки от мгновенного чтения. Но если это действительно необходимо, вы могли бы ввести свой собственный простой класс, содержащий два целых числа и имеющий несколько надежных имен свойств. Также в настоящее время теряется информация о том, является ли каждый блок общим для обеих строк или они разные. Но, опять же, должно быть довольно просто получить эту информацию также в кортеже или в вашем собственном классе.
Комментарии:
1. Таким образом, заданными будут две переменные: var1 = «bc3231dsc»; var2 = «bc3462dsc»; После сравнения каждого символа из var1 в var2 я бы хотел, чтобы результат был: leftMatch = «bc3»; center1 = «231»; center2 = «462»; rightMatch = «dsc»; Как мне поместить совпадающие символы в переменные, как показано в выводе, который я указал?
Ответ №3:
static void Main(string[] args)
{
string test1 = "bc3231dsc";
string tes2 = "bc3462dsc";
string firstmatch = GetMatch(test1, tes2, false);
string lasttmatch = GetMatch(test1, tes2, true);
string center1 = test1.Substring(firstmatch.Length, test1.Length -(firstmatch.Length lasttmatch.Length)) ;
string center2 = test2.Substring(firstmatch.Length, test1.Length -(firstmatch.Length lasttmatch.Length)) ;
}
public static string GetMatch(string fist, string second, bool isReverse)
{
if (isReverse)
{
fist = ReverseString(fist);
second = ReverseString(second);
}
StringBuilder builder = new StringBuilder();
char[] ar1 = fist.ToArray();
for (int i = 0; i < ar1.Length; i )
{
if (fist.Length > i 1 amp;amp; ar1[i].Equals(second[i]))
{
builder.Append(ar1[i]);
}
else
{
break;
}
}
if (isReverse)
{
return ReverseString(builder.ToString());
}
return builder.ToString();
}
public static string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
Ответ №4:
Псевдокод того, что вам нужно..
int stringpos = 0
string resultstart = ""
while not end of string (either of the two)
{
if string1.substr(stringpos) == string1.substr(stringpos)
resultstart =resultstart string1.substr(stringpos)
else
exit while
}
в resultstart есть начальная строка.. вы можете сделать то же самое, перейдя назад…
Ответ №5:
Другое решение, которое вы можете использовать, — это регулярные выражения.
Regex re = new Regex("^bc3.*?dsc$");
String first = "bc3231dsc";
if(re.IsMatch(first)) {
//Act accordingly...
}
Это дает вам больше гибкости при сопоставлении. Приведенный выше шаблон сопоставляет любую строку, которая начинается в bc3 и заканчивается в dsc, с чем угодно, кроме перевода строки. Изменив .*? на d, вы можете указать, что вам нужны только цифры между двумя полями. Отсюда возможности безграничны.
Ответ №6:
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
class Sample {
static public void Main(){
string s1 = "bc3231dsc";
string s2 = "bc3462dsc";
List<string> common_str = commonStrings(s1,s2);
foreach ( var s in common_str)
Console.WriteLine(s);
}
static public List<string> commonStrings(string s1, string s2){
int len = s1.Length;
char [] match_chars = new char[len];
for(var i = 0; i < len ; i)
match_chars[i] = (Char.ToLower(s1[i])==Char.ToLower(s2[i]))? '#' : '_';
string pat = new String(match_chars);
Regex regex = new Regex("(# )", RegexOptions.Compiled);
List<string> result = new List<string>();
foreach (Match match in regex.Matches(pat))
result.Add(s1.Substring(match.Index, match.Length));
return resu<
}
}
Ответ №7:
для УСЛОВИЯ ОБНОВЛЕНИЯ
using System;
class Sample {
static public void Main(){
string s1 = "bc3231dsc";
string s2 = "bc3462dsc";
int len = 9;//s1.Length;//cond.1)
int l_pos = 0;
int r_pos = len;
for(int i=0;i<len amp;amp; Char.ToLower(s1[i])==Char.ToLower(s2[i]); i){
l_pos;
}
for(int i=len-1;i>0 amp;amp; Char.ToLower(s1[i])==Char.ToLower(s2[i]);--i){
--r_pos;
}
string leftMatch = s1.Substring(0,l_pos);
string center1 = s1.Substring(l_pos, r_pos - l_pos);
string center2 = s2.Substring(l_pos, r_pos - l_pos);
string rightMatch = s1.Substring(r_pos);
Console.Write(
"leftMatch = "{0}"n"
"center1 = "{1}"n"
"center2 = "{2}"n"
"rightMatch = "{3}"n",leftMatch, center1, center2, rightMatch);
}
}