用于字符串比较

问题描述:

Ruby程序我有红宝石字符串比较代码中我得到一些奇怪的输出用于字符串比较

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_? – 2015-02-06 12:06:27

+0

如果matchval_not_pos(“abc”,“abc”) => 0 &pry(main)> matchval_not_pos(“abcde”,“abc”)=> 2如果直到3个字符串匹配,在str1中增加charector字符串like(“abcdefg”,“abcd”)它给了我错误的输出 – user4537116 2015-02-06 12:09:53

+1

你可能做的一件事是将'matchval_not_pos'分解成更小的方法并为每种方法编写单元测试。实际上可能会帮助您更快地进行调试,此外您还可以测试所有边界案例。 – aceofbassgreg 2015-02-06 15:23:02

我没有经历过,整个阅读剪断你贴,但我注意到像你期望它这部分将不工作:

[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!

为了说明standfarback指出的问题,让我们来看看为什么在循环中从数组中删除项目不是你的方法。

比方说,我们有以下值的两个数组:

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"] 

看看发生了什么?我们删除了数组中的第一个元素,现在一切都在向下滑动以填充空白。所以,现在我们第二次穿过循环,现在i1。我们将看看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,你应该把它分解成更小的方法,并为变量提供更有意义的名称。

我希望这可以帮助您了解在循环过程中如何从阵列中移除元素可以提供奇怪的结果。