2013-09-26 5 views
3

Я разработал следующий код для сравнения двух ячеек (строк) в столбцах A и D и записи значения D-ячейки в соответствующей B-ячейке, если найдено парное совпадение.Сравнение элементов двух строк

Sub CompareAndGuess() 
Dim strLen, aux As Integer 
Dim max1, max2 As Long 
Dim str As String 

Range("A1").Select 
Selection.End(xlDown).Select 
max1 = ActiveCell.Row 
Range("D1").Select 
Selection.End(xlDown).Select 
max2 = ActiveCell.Row 

For a = 2 To max1 
    str = Cells(a, 1) 
    str = StrConv(str, vbUpperCase) 
    strLen = Len(str) 
    aux = strLen 

    For l = 3 To strLen 
     For d = 2 To max2 
      If Cells(d, 4) = Left(str, aux) Then 
       Cells(a, 2) = Cells(d, 4) 
       Exit For 
      ElseIf Cells(d, 4) = Right(str, aux) Then 
       Cells(a, 2) = Cells(d, 4) 
       Exit For 
      End If 
     Next d 

     aux = aux - 1 
     If Cells(a, 2) <> "" Then 
      Exit For 
     End If 
    Next l 
    Cells(a, 2).Select 
Next a 
End Sub 

Может кто-нибудь помочь мне найти, где это проблема, потому что когда я его запускаю код только угадает правильный один ряд из 50, тогда как он должен соответствовать по крайней мере 40 или около того.

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

образец данных я анализирующая является: имен с опечатками: -

Jatiuca 
Pajuara 
Poco 
Santa Luzia 
Pajucara 
Domingos Acacio 
Jaragua 
Stella Maris 
P Verde 
Tabuleiro dos Martin 
Gruta Lourdes 
Brasilia 
Centro Historico 
Monumento 
Tabuleiro dos Martins 

имен с опечатками для поиска по этому списку: -

JARAGUÁ 
TABULEIRO DO MARTINS 
CENTRO 
BRASÍLIA 
CACIMBAS 
JATIÚCA 
CAITITUS 
PAJUÇARA 
CANAÃ 
PONTA VERDE 
CANAFÍSTULA 
POÇO 
CAPIATÃ 
CAVACO 
SANTA LÚCIA 
+1

VB имеет 'функцию InStr', которая может представлять интерес здесь. .. –

+0

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

+0

Как в стороне, не очень хорошая практика использовать 'l' таким образом. – pnuts

ответ

3

Я нашел правильный способ сделать это с помощью каждого. Вот оно:

 If InStr(1, Cells(d, 4), Left(str, aux)) = 1 Then 
      Cells(a, 2) = Cells(d, 4) 
      Exit For 
     ElseIf InStr(Cells(d, 4), Right(str, aux)) + strLen - aux = strLen Then 
      Cells(a, 2) = Cells(d, 4) 
      Exit For 
     End If 
+1

Это кажется невероятно ненадежным, я ошибаюсь или буду это заменит любое слово, содержащее первую или последнюю 3 буквы слова в списке? Почему даже оба с петлей различной длины, почему бы просто не сделать только один цикл из первых и последних трех букв? – user2140261

+0

Это, кажется, не функционирует всегда на самом деле. Я не ищу только 3, потому что поиск букв 4, 5, 6 и т. Д. Лучше, чем поиск только 3, где два или более слова могут иметь эти 3, но не те 4, 5, 6 и т. Д. –

+0

, но это может отменяйте неправильные слова неправильными словами, потому что они содержат 3, хотя имена сильно различаются. – user2140261

0

Я рад, что вы решили эту проблему самостоятельно с помощью функции InStr. Причина, по которой ваш код плохо работал, заключается в том, что вы сравнивали сокращенные версии имен с полноразмерными версиями. Изменение более раннего кода с помощью следующего поиска позволило бы найти гораздо больше совпадений.

  If Left(Cells(d, 4), aux) = Left(str, aux) Then 
       Cells(a, 2) = Cells(d, 4) 
       Exit For 
      ElseIf Right(Cells(d, 4), aux) = Right(str, aux) Then 
       Cells(a, 2) = Cells(d, 4) 
       Exit For 
      End If 
+0

Я считаю, что это будет работать, только если оба слова с опечатками и без опечаток имеют одинаковую длину. Что не происходит. Спасибо в любом случае –

+0

@BrunoMartins ему нужно было бы только сравнить начало или конец слов, попробовал его по вашим данным образца и нашел 10 совпадений, но не POÇO. –

+0

В данный момент я использую что-то похожее на то, что вы разместили здесь, но без «aux» в левой части каждого сравнения и с другой переменной, поэтому я запускаю все комбинации, чтобы найти наилучшее совпадение. –

0

Это абсолютно UNTESTED

Я буду переписывать завтра, и очистить его, но это основной способ действительно знаю, что вы сопоставляя правильные слова. Это может занять немного больше времени, и я ускорит его МНОГО завтра, но сейчас это шкаф способ проверить слова на валидность

'Go through all possibly typod words 
For each rngTestCell in Range("yourlist") 

    'For each possibly typod word test if against every correct value 
    For each rngCorrectedValue in Range("ListOfCorrectValues") 

     'start by testing length to weed out most values quick 
     'Test any words that are within 3 letters of each other, can be less 
     'could add a tet for first and last letters match also before starting 
     'to match every letter also, just a top level weeding of words 
     If (Len(rngTestCell) - Len(rngCorrectedValue)) < 3 Then 

      'loop each letter in the words for match keep a record of how many are matched 
      for i = 1 to Len(rngTestCell) 

       If rngTestCell.Character(i,1) = rngCorrectedValue.Characters(i,1) Then 
        NumberOfMatches = NumberOfMatches + 1 
       End If 

      next i 

      'if enough of the letters match replace the word, this will need updating because 
      'i feel using a ratio of more then 10% of the words match then replace 
      'but for now if more then 2 letters don't match then it isn't a match 
      If (Len(rngTestCell) - NumberOfMatches) > 2 Then 'Less then 2 letters are different 
       rngTestCell.Offset(,1).Value = rngCorrectedValue.Value 
       Exit Loop 
      End If 

     End If 

    Next rngCorrectedValues 

Next rngTestCell 
+0

Наверное, оптимальным вариантом было бы усовершенствованная версия алгоритма Smith-Waterman, оптимизированная для соответствия языку? Вероятно, вы могли бы использовать 1 для каждого совпадающего символа и -1 для каждого несимметричного, вставки или удаления. Возможно, чрезмерное проектирование решения. –

+0

@GrahamAnderson Это было сделано на самом деле быстрее, чем доказательство концепции, но на данный момент это единственный ответ, который не заменит «CANAFISTULA» на «CANAû, в то время как «CANAFISTULA» следует заменить на «CANAFÍSTULA», далее если в списке было правильное слово 'CANAFÍSTULA', оно будет заменено на' CANAÃ', этот пример не будет иметь этой ошибки. Дело в том, что вы не должны неправильно заменять вещи. Я не вижу, как это перерабатывает что-либо, если есть более простой способ получить те же результаты, то да, это было бы, но это было самым простым, о котором я мог думать. – user2140261

+0

Ни мой метод, ни я не подозреваю, что Бруно заменит CANAFISTULA на CANAÃ, когда правильное имя CANAFÍSTULA находится в правильном списке, потому что цикл заканчивается после первого (и, следовательно, самого длинного) совпадения. Я действительно думаю, что ваш метод более надежный. Извините за любое нарушение, вызванное замечанием инженера, я имел в виду это для рассмотрения использования алгоритма типа Smith-Waterman. Они обычно используются для выравнивания последовательностей белков или нуклеиновых кислот. Он будет проверять каждое возможное полное/частичное совпадение между каждой парой строк и, как таковое, можно считать немного большим. –

Смежные вопросы