2015-02-06 5 views
0

У меня есть строка кода сравнения в рубина, в котором я получаю некоторые странные выходпрограмма рубин для сравнения строк

def matchval_not_pos(str1, str2) 
    a1, a2 = str1.chars, str2.chars 
    return 0 if a1 == a2 
    [a1.size, a2.size].min.times do |i| 
    if a1[i] == a2[i] 
     a1.delete_at(i) 
     a2.delete_at(i) 
    end 
    end 
    a1.reduce(0) do |t,c| 
    i = a2.index(c) 
    if i 
     inc = 1 
     a2.delete_at(i) 
    else 
     inc = 0 
    end 
    t + inc 
    end 
end 

Я получаю выход на Поддеть консоли

=> :matchval_not_pos 
[12] pry(main)> matchval_not_pos("abc","abc") 
=> 0 
[13] pry(main)> matchval_not_pos("abcd","abc") 
=> 1 
[14] pry(main)> matchval_not_pos("abcde","abc") 
=> 1 
[15] pry(main)> matchval_not_pos("abcdef","abc") 
=> 1 
[16] pry(main)> matchval_not_pos("abcdefgh","abc") 
=> 1 
[17] pry(main)> matchval_not_pos("abcdefgh","abcdefghi") 
=> 4 
[18] pry(main)> matchval_not_pos("abcdefgh","abcdefghijklmn") 
=> 4 
[19] pry(main)> matchval_not_pos("abcdefghijklmn","abcdefghijklmn") 
=> 0 
[20] pry(main)> matchval_not_pos("abcdefghijklmnop","abcdefghijklmn") 
=> 7 
[21] pry(main)> matchval_not_pos("abcdefghijklmnop","abcdefghijklmnop") 
=> 0 
[22] pry(main)> matchval_not_pos("abcdefghijklmnop","abcdefghijklmnopqw") 
=> 8 
[23] pry(main)> matchval_not_pos("abcdefghijklmnop","abcdefghijklmnop") 
=> 0 

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

+3

Какой выход _were_ вы ожидаете? –

+0

Если matchval_not_pos ("abc", "abc") => 0 & pry ​​(main)> matchval_not_pos ("abcde", "abc") => 2 Если вы отметите, что три строки charecters правильно соответствуют, но если i увеличенная строка charector в str1 like ("abcdefg", "abcd"), это дает мне неправильный вывод – user4537116

+1

Одна вещь, которую вы можете сделать, это разбить 'matchval_not_pos' на более мелкие методы и написать единичные тесты для каждого метода. Возможно, это поможет вам быстрее отладить это, плюс вы сможете протестировать все случаи краев. – aceofbassgreg

ответ

0

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

[a1.size, a2.size].min.times do |i| 
    if a1[i] == a2[i] 
    a1.delete_at(i) 
    a2.delete_at(i) 
    end 
end 

Ошибка здесь в том, что вы изменяете массив (с #delete_at) в то же время, что и цикл.

Т.е. Если вы a1.delete_at(1), вы изменяете индексы всех символов после индекса 1 и изменяете длину массива.

В принципе, все выходит из строя.

Одним из решений в этом случае является a1[i] = nil вместо a1.delete_at(i), а затем вне петли делать a1.compact!.

0

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

Допустим, у нас есть два массива следующих значений:

x = ["a", "b", "c", "d"] 
y = ["a", "b", "c", "d", "e", "f", "g"] 

Теперь давайте поместим их через петлю:

[x.size, y.size].min.times do |i| 
    if x[i] == y[i] 
     x.delete_at(i) 
     y.delete_at(i) 
    end 
end 

Это означает, что мы будем цикл 4 раза. В первый раз по петле i будет 0. Таким образом, x[0] - "a" и y[0] - "a". Это означает, что мы имеем .delete_at(0) на обоих массивах. Это означает, что после первого цикла наши массивы будут такими:

x = ["b", "c", "d"] 
y = ["b", "c", "d", "e", "f", "g"] 

Посмотрите, что произошло? Мы удалили первый элемент в массивах, и теперь все сбрасывается, чтобы заполнить пустоту. Итак, теперь мы путешествуем по петле второй раз, и теперь i - 1. Будем смотреть на x[1] и y[1] что сравнивается "c" и "c". Мы полностью пропустили "b".

Это означает, что вы проверяете только каждый элемент.

Существует множество возможных решений для сравнения массивов, но если вы влюблены в концепцию использования .delete_at, вы рассмотрели использование метода .downto? Он будет иметь такое же влияние, как и .times, но оно начнется с числа и уменьшится. Итак:

([x.size, y.size].min - 1).downto(0) do |i| 
    if x[i] == y[i] 
     x.delete_at(i) 
     y.delete_at(i) 
    end 
end 

Теперь, когда мы пройдем через цикл в первый раз, мы сначала рассмотрим последний элемент.Итак, если мы будем .delete_at(3), он не вышвырнет нас на следующей итерации.

Опять же, это не лучшее решение, но это возможное решение. Я согласен с aceofbassgreg, что вы должны разбить это на более мелкие методы и предоставить более значимые имена переменным.

Надеюсь, это поможет вам узнать, как удаление элементов из массива во время цикла может обеспечить нечетные результаты.