2015-04-08 7 views
0

Я работаю над приложением, и я хотел бы (если это возможно), чтобы иметь возможность сравнивать 2 строки, которые многослойны.Сравнение двух многострочных строк

Например:

string1= 
001000 
000100 
000100 

string4= 
10001000 
00100100 
00000100 

string2= 
10 
01 
01 

string3= 
010 
010 
010 

Выход:

string1.contains(string2) > true 
string1.contains(string3) > false 
string4.contains(string2) > true 
string4.contains(string3) > false 

Мне нужна функция, которая в состоянии видеть, что string1 содержит string2. Я экспериментировал, но еще не нашел ответа, который отвечал моим потребностям. Мне нужно, чтобы он мог видеть, что он содержит строку, в которой линии расположены относительно друг друга (например, строка1 должна иметь 10 на одной строке и 01 непосредственно под ней и т. Д.)

Если функция возможна то он должен возвращать значение true для «string1 содержит строку2), а false для« string 1 содержит string3 »,

Любая помощь, которую вы можете дать, была бы очень благодарна (используйте, по возможности, VB, C# или аналогичные коды)

Заранее благодарен

+0

Включая или исключая 'CRLF'? – OneFineDay

+0

Для каждой строки в многострочной подсчете отдельно для части содержит? Нам нужен пример ожиданий возврата с вашим примером. – OneFineDay

+0

Не нужно искать CRLF в конце строки, если это то, что вы имеете в виду? – user2625752

ответ

1

Основываясь на ваш комментарий на @ RufusL-х answer:

Это выглядит многообещающим, но я не уверен, что это будет работать, как string1 не всегда будет 3 линии длиной. Но ваш код выглядит легко адаптируемым, чтобы он проходил через линии, если они имели разную длину :)

Я предполагаю, что источник, который нужно сравнить, может содержать больше «строк», чем строка сравнения. Таким образом, шаги, которые следует предпринять, в основном:

  1. Преобразование источника и сравнение строк в строках.
  2. Хотя в источнике есть достаточные начальные строки кандидата, попробуйте найти подходящую стартовую строку.
  3. Если найдена совпадающая подстрока в строке исходного кода кандидата, убедитесь, что все последующие строки соответствуют этой позиции подстроки. Если они делают => соответствие

Ниже приведен фрагмент кода, реализующий этот алгоритм в методе расширения C#.

public static class LinesMatcher 
{ 
    public static int CountMatches(this string source, string toCompare, params string[] lineSeparators) 
    { 
     // split into parts. 
     var srcParts = source.Split(lineSeparators, StringSplitOptions.RemoveEmptyEntries); 
     var cmpParts = toCompare.Split(lineSeparators, StringSplitOptions.RemoveEmptyEntries); 

     // check until candidate first matching source lines have been exhausted. 
     var matchCount = 0; 
     var startLineNdx = 0; 
     while (cmpParts.Length <= (srcParts.Length - startLineNdx)) 
     { 
      // search for a match from the start of the current line. 
      var matchNdx = srcParts[startLineNdx].IndexOf(cmpParts[0]); 
      while (matchNdx >= 0) 
      { 
       // Line has a match with the first line in cmpParts 
       // Check if all subsequent lines match from the same position. 
       var match = true; 
       for (var i = 1; i < cmpParts.Length; i++) 
       { 
        if (srcParts[startLineNdx + i].IndexOf(cmpParts[i], matchNdx) != matchNdx) 
        { 
         match = false; 
         break; 
        } 
       } 
       if (match) // all lines matched 
        matchCount++; 

       // try to find a next match in this line. 
       matchNdx = srcParts[startLineNdx].IndexOf(cmpParts[0], matchNdx + 1); 
      } 

      // Try next line in source as matching start. 
      startLineNdx++; 
     } 
     return matchCount; 
    } 
} 

Использование:

class Program 
{ 
    public static void Main(params string[] args) 
    { 
     var seps = new[] { "\n" }; 
     var string0 = "00000010\n001000\n000100\n000100"; 
     var string1 = "001000\n000100\n000100"; 
     var string4 = "10001000\n00100100\n00000100"; 
     var string2 = "10\n01\n01"; 
     var string3 = "010\n010\n010"; 

     Console.WriteLine(string1.CountMatches(string2, seps)); 
     Console.WriteLine(string1.CountMatches(string3, seps)); 
     Console.WriteLine(string4.CountMatches(string2, seps)); 
     Console.WriteLine(string4.CountMatches(string3, seps)); 
     Console.WriteLine(string0.CountMatches(string2, seps)); 
    } 
} 
+0

Работал отлично, когда я его протестировал .. Спасибо! – user2625752

+0

Есть ли способ, которым ваш код может быть отредактирован, чтобы подсчитать найденные им события. Например, если string1 = "001000 \ n000100 \ n000100 \ n001000 \ n000100 \ n000100" и вы выполнили "string1.ContainsAllOf (string2, seps)", он вернет 2, так как содержит 2 строки строки2 ..? – user2625752

+1

Да, это довольно просто, вместо того, чтобы останавливать и возвращать 'true', когда найдено совпадение, просто увеличивайте счетчик на количество найденных совпадений. Я обновлю ответ, чтобы сделать это. – Alex

0

Я только что внедрил его в Groovy (старался не использовать какой-то Groovy-специфический синтаксис ах).
Вот Gist: https://gist.github.com/s0nerik/9c52175dcd68ad8807b8

Мое решение предполагает, что обе строки имеют одинаковую высоту (количество строк), и каждая строка в пределах каждой строки имеет ту же длину. Также предполагается, что каждая строка первой строки имеет большую или равную длину по сравнению со второй строкой.

+0

Вы также должны включить свой код в свой ответ здесь. – hatchet

0

Вы можете написать расширение для string класса, чтобы сделать это:

public static class StringExtensions 
{ 
    public static bool MultiContains(this string source, string compare) 
    { 
     if (source == null) return compare == null; 
     if (compare == null) return false; 

     var sourceParts = source.Split('\n'); 
     var compareParts = compare.Split('\n'); 

     if (sourceParts.Length != compareParts.Length) return false; 

     // Try to get a match with the first pair of strings 
     int firstMatchIndex = sourceParts[0].IndexOf(compareParts[0]); 

     // If we didn't find any matches in the first pair, return false 
     if (firstMatchIndex == -1) return false; 

     // If there are no other matches to be compared, return true 
     if (sourceParts.Length == 1) return true; 

     var matched = false; 

     // Otherwise, see if all compare matches are at same position 
     while (!matched && firstMatchIndex > -1) 
     { 
      for (int i = 1; i < sourceParts.Length; i++) 
      { 
       // See if we have a match in the same position as the first match 
       matched = sourceParts[i].IndexOf(compareParts[i], 
        firstMatchIndex) == firstMatchIndex; 

       if (!matched) 
       { 
        // If one of the strings didn't match in the same position, 
        // try to find another match in the first lines 
        firstMatchIndex = sourceParts[0].IndexOf(compareParts[0], 
         firstMatchIndex + 1); 

        break; 
       } 
      } 
     } 

     return matched; 
    } 
} 

И тогда использование будет выглядеть так:

public static void Main() 
{ 
    var string1 = "001000\n000100\n000100"; 
    var string4 = "10001000\n00100100\n00000100"; 
    var string2 = "10\n01\n01"; 
    var string3 = "010\n010\n010"; 

    Console.WriteLine(string1.MultiContains(string2)); 
    Console.WriteLine(string1.MultiContains(string3)); 
    Console.WriteLine(string4.MultiContains(string2)); 
    Console.WriteLine(string4.MultiContains(string3)); 
} 

Выход:

Правда
False
True
Ложные

+0

Можете ли вы предположить, что строка сравнения имеет одинаковое количество строк? – SILENT

+0

Это выглядит многообещающим, но я не уверен, что он будет работать, поскольку string1 не всегда будет длиной 3 строки. Но ваш код выглядит легко адаптируемым, чтобы заставить его циклически перемещаться по линиям, если они имеют разную длину:) – user2625752

+0

@SILENT Я выполняю его, не предполагая. Не уверен, что я понимаю, что вы говорите? –

0

Попробуйте это:

Sub Main() 
    Dim string1 = String.Join(vbCrLf, "001000", "000100", "000100") 
    Dim string4 = String.Join(vbCrLf, "10001000", "00100100", "00000100") 
    Dim string2 = String.Join(vbCrLf, "10", "01", "01") 
    Dim string3 = String.Join(vbCrLf, "010", "010", "010") 

    Console.WriteLine("String1 contains String2 {0}", string1.ContainsPattern(string2)) 
    Console.WriteLine("String1 contains String3 {0}", string1.ContainsPattern(string3)) 
    Console.WriteLine("String4 contains String2 {0}", string4.ContainsPattern(string2)) 
    Console.WriteLine("String4 contains String3 {0}", string4.ContainsPattern(string3)) 
    Console.ReadKey() 
End Sub 

<Extension> Function ContainsPattern(target As String, pattern As String) As Boolean 
    Dim lines = Split(target, vbCrLf) 
    Dim patternLines = Split(pattern, vbCrLf) 

    If lines.Count <> patternLines.Count Then 
     Throw New ArgumentException("Line counts differ") 
    End If 

    If patternLines.First.Length > lines.First.Length Then 
     Throw New ArgumentException("Pattern exceeds target") 
    End If 

    Dim match = False 
    For m = 0 To (lines.First.Length - patternLines.First.Length) 
     match = True 
     For l = 0 To lines.Count - 1 
      If Not lines(l).Substring(m).StartsWith(patternLines(l)) Then 
       match = False 
       Exit For 
      End If 
     Next 
     If match = True Then 
      Return True 
     End If 
    Next 

    Return False 
End Function 
0

Самое лучшее, что нужно сделать, это принять ваши строки в одну строку. И затем создайте функцию, которая проверяет количество чисел в вашей строке. Второй параметр вашей функции, который вы должны дать, - количество чисел, в которых вы получаете строку.

Тогда простой раздел может проверить, сколько строк оно должно быть автоматически. Что-то вроде этого:

Module Module1 

    Sub Main() 

     Dim string1 As String = "001000000100000100" 

     Dim string2 As String = "100101" 

     Dim string3 As String = "010010010" 
     Dim string4 As String = "100010000010010000000100" 


     Dim string1Split As List(Of String) = SplitUp(string1, 6) 
     Dim string2Split As List(Of String) = SplitUp(string2, 2) 
     Dim string3Split As List(Of String) = SplitUp(string3, 3) 
     Dim string4Split As List(Of String) = SplitUp(string4, 8) 

     For Each x As String In string1Split 
      Console.WriteLine("string1 " + x) 
     Next 
     For Each x As String In string2Split 
      Console.WriteLine("string2 " + x) 
     Next 
     For Each x As String In string3Split 
      Console.WriteLine("string3 " + x) 
     Next 
     For Each x As String In string4Split 
      Console.WriteLine("string4 " + x) 
     Next 

     Console.ReadLine() 

    End Sub 

    Public Function SplitUp(number As String, linebreak As Integer) As List(Of String) 

     Dim numberLength As Integer = number.Length 
     Dim timesToGo As Integer = numberLength \ linebreak 


     Dim listwithStrings As New List(Of String) 


     For a As Integer = 1 To timesToGo 

      Dim value1 As String = number.Substring(0, linebreak) 
      Dim value2 As String = number.Substring(linebreak) 
      listwithStrings.Add(value1) 
      number = value2 
     Next 



     Return listwithStrings 


    End Function 


End Module 

Последняя вещь, которую вы должны сделать, это взять строку из списка (одна строка цифр) и сравнить его с другой линией строки из другого списка. , если две или более цифр совпадают, тогда удерживайте цифру, где начинается матч. Затем используйте эту цифру, чтобы проверить обе третьи строки из списка 2.

Вы можете следовать? xD

0

Попробуйте это. Я думаю, что охватывает большинство, если не все ситуации:

const char stringSplit = '\n'; 
    public static bool contains(this string s, string cmp) 
    { 
     var t0l = s.IndexOf(stringSplit); 
     var c0l = cmp.IndexOf(stringSplit); 

     var d = t0l - c0l; 
     if (t0l == -1 || c0l == -1 || d < 0) 
      return false; 
     var tc = s.Replace(stringSplit.ToString(), ""); 
     var cs = cmp.Split(stringSplit); 
     string regS = ""; 
     foreach (var c in cs) 
     { 
      if (regS == "") 
       regS = c; 
      else 
       regS += ".{" + d + "}" + c; 
     } 
     return Regex.IsMatch(tc, regS); 
    } 
Смежные вопросы