我遇到了需要使用方法比较数组中两个元素的情况。我发现使用嵌套循环的逻辑非常简单,但这可能不是Ruby的好用。
对于前。确定数组是否有任何一对2个等于0的数字:
def pairs(array)
i = 0
while i < array.length
y = i + 1
while y < array.length
if array[i] + array[y] == 0
return true
end
y += 1
end
i += 1
end
return false
end
或者如果我想看看数组中的两个东西是否相同,我会使用相同的逻辑,除了set:if array [i] == to array [y] ...
有人能为这样的问题提供更好的方法吗?
答案 0 :(得分:12)
通常,您可以将英语规范直接翻译成Ruby。
在第一个问题中,您询问两个元素的任何组合是否增加为零。当您想要知道可枚举的任何元素是否为真时使用的方法是Enumerable#any?
。如果要处理数组中元素的组合,可以使用方法Array#combination
。对于求和,您可以使用Numeric#+
或Enumerable#inject
,如果您想知道数字是否为零,则可以使用Numeric#zero?
。
因此,您的第一个问题的可能实现将是:
ary.combination(2).any? {|pair| pair.inject(:+).zero? }
你的第二个问题可以通过以下方式回答:
ary.combination(2).any? {|a, b| a == b }
在这两种情况下,当然还有其他方法可以做到这一点。例如,在第一种情况下,我们可以观察到两个数字总和为零的唯一方法是,如果一个是另一个的负数。
请注意,循环中通常出错的事情的 none 可能会在此处发生。没有off-by-one错误,没有fencepost错误,没有错误的终止条件,没有迭代结束数组,只是因为没有循环。
答案 1 :(得分:1)
如果您只想计算数组中元素的出现次数,可以使用Enumerable#count
uniq
现在,如果您想查看数组中是否有重复条目,可以使用def has_duplicates?(arr)
arr.uniq.length == arr.length
end
方法
{{1}}
答案 2 :(得分:1)
这是我对你的第一个问题的处理方法以及另一个返回对的方法:
def pairs?(arr)
arr.inject(false){|c, v| c || (arr.include?(-v) && v > 0)}
end
def get_pairs(arr)
arr.collect{|val| [val, -val] if arr.include?(-val) && val > 0}.reject(&:nil?)
end
arr = [1, 8, -2, 12, -15, 5, 3]
p pairs?(arr)
p get_pairs(arr)
arr = [1, 8, -2, 12, -15, 5, 3, 2, -3, 1]
p pairs?(arr)
p get_pairs(arr)
输出:
false
[]
true
[[3, -3], [2, -2]]
但是,当有一对零时,他们不会工作。您可以明确处理该案例,也可能有人可以提供更好的解决方案。
答案 3 :(得分:1)
你会喜欢Ruby,部分原因是你通常不会使用索引来提取或设置数组的元素。
<强>代码强>
def pairs(arr)
arr.map { |e| e < 0 ? -e : e }.
group_by(&:itself).
select { |_,v| v.size > 1 }.
keys
end
<强>实施例强>
pairs [1, 8, -2, 12, -15, 5, 3] #=> []
pairs [1, 8, -2, 12, -15, 5, 3, 2, -3, 1] #=> [1, 2, 3]
如果您希望第二个示例返回[[1, -1], [2, -2], [3, -3]]
(虽然我不明白这一点),请将方法的倒数第二行替换为:
map { |k,_| [k, -k] }
<强>解释强>
以下步骤:
arr = [1, 8, -2, 12, -15, 5, 3, 2, -3, 1]
是:
a = arr.map { |e| e < 0 ? -e : e }
#=> [1, 8, 2, 12, 15, 5, 3, 2, 3, 1]
b = a.group_by(&:itself)
#=> {1=>[1, 1], 8=>[8], 2=>[2, 2], 12=>[12], 15=>[15], 5=>[5], 3=>[3, 3]}
我们在Ruby v2.2中获得了Object#itself。对于早期版本,请使用:
b = a.group_by { |e| e }
继续:
c = b.select { |_,v| v.size > 1 }
#=> {1=>[1, 1], 2=>[2, 2], 3=>[3, 3]}
c.keys
#=> [1, 2, 3]
该行:
select { |_,v| v.size > 1 }
可写:
select { |k,v| v.size > 1 }
其中k
和v
代表&#34; key&#34;和&#34;值&#34;,但由于k
未在块计算中使用,因此通常的做法是将k
替换为局部变量_
(是的,它&#39} ;一个变量 - 在IRB中尝试它,主要是为了告知读者该块中没有使用该参数。
如果arr = [1, 1, -1, -1, 2, -2]
,则会返回[1,2]
。如果您希望它返回[1,1,2]
,您必须采取不同的方法。