сравните символы в двух строках

#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:

После прочтения вашего вопроса и уже заданных ответов я думаю, что отсутствуют некоторые ограничения, которые, возможно, очевидны для вас, но не для сообщества. Но, может быть, мы можем сделать небольшую догадку:

  1. У вас будет куча пар строк, которые следует сравнить.
  2. Две строки в каждой паре имеют одинаковую длину, или вас интересует только сравнение символов, прочитанных одновременно слева направо.
  3. Получите какое-то перечисление, которое сообщает мне, где начинается каждый блок и какой он длины.

В связи с тем, что строка представляет собой всего лишь перечисление символов, вы можете использовать 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);
    }
}