给定两个等长的字符串使得
s1 = "ACCT"
s2 = "ATCT"
我想找出字符串不同的位置。所以我做了这个。 (请提出更好的方法。我敢打赌应该有)
z= seq1.chars.zip(seq2.chars).each_with_index.map{|(s1,s2),index| index+1 if s1!=s2}.compact
z 是两个字符串不同位置的数组。在这种情况下 z 返回 2
假设我添加了一个新字符串
s3 = "AGCT"
我想将它与其他字符串进行比较,看看这 3 个字符串的不同之处。我们可以采用与上述相同的方法,但这次
s1.chars.zip(s2.chars,s3.chars)
返回数组的数组。给定两个字符串,我只是在比较两个字符是否相等,但随着我添加更多字符串,它开始变得难以承受并且随着字符串变得更长。
#=> [["A", "A", "A"], ["C", "T", "G"], ["C", "C", "C"], ["T", "T", "T"]]
运行
s1.chars.zip(s2.chars,s3.chars).each_with_index.map{|item| item.uniq}
#=> [["A"], ["C", "T", "G"], ["C"], ["T"]]
可以帮助减少冗余并返回完全相同的位置(大小为 1 的非空子数组)。然后我可以打印出大小 > 1 的子数组的索引和内容。
s1.chars.zip(s2.chars,s3.chars,s4.chars).each_with_index.map{|item| item.uniq}.each_with_index.map{|a,index| [index+1,a] unless a.size== 1}.compact.map{|h| Hash[*h]}
#=> [{2=>["C", "T", "G"]}]
我觉得随着字符串数量的增加和字符串长度的增加,这会逐渐停止或变慢。有哪些最佳替代方法可以做到这一点? 谢谢。
最佳答案
这是我要开始的地方。我故意使用不同的字符串,以便更容易看出差异:
str1 = 'jackdaws love my giant sphinx of quartz'
str2 = 'jackdaws l0ve my gi4nt sphinx 0f qu4rtz'
获取第一个字符串的字符:
str1.chars.with_index.to_a - str2.chars.with_index.to_a
=> [["o", 10], ["a", 19], ["o", 30], ["a", 35]]
获取第二个字符串的字符:
str2.chars.with_index.to_a - str1.chars.with_index.to_a
=> [["0", 10], ["4", 19], ["0", 30], ["4", 35]]
随着字符串变大,速度会稍微变慢,但不会很糟糕。
编辑:添加了更多信息。
如果您有任意数量的字符串,并且需要将它们全部进行比较,请使用Array#combination
:
str1 = 'ACCT'
str2 = 'ATCT'
str3 = 'AGCT'
require 'pp'
pp [str1, str2, str3].combination(2).to_a
>> [["ACCT", "ATCT"], ["ACCT", "AGCT"], ["ATCT", "AGCT"]]
在上面的输出中,您可以看到 combination
循环遍历数组,返回数组元素的各种 n
大小的组合。
pp [str1, str2, str3].combination(2).map{ |a,b| a.chars.with_index.to_a - b.chars.with_index.to_a }
>> [[["C", 1]], [["C", 1]], [["T", 1]]]
使用组合的输出,您可以循环遍历数组,将所有元素相互比较。因此,在上面返回的数组中,在“ACCT”和“ATCT”对中,'C' 是两者之间的差异,位于字符串中的位置 1。类似地,在“ACCT”和“AGCT”中,差异再次是“C”,在位置 1。最后对于“ATCT”和“AGCT”,它是在位置 1 的“T”。
因为我们已经在较长的字符串示例中看到代码将返回多个更改的字符,所以这应该让您非常接近。
关于ruby - 比较等长的字符串并注意差异发生的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5829165/