使用Ruby

时间:2015-11-24 22:40:12

标签: ruby

我遇到了需要使用方法比较数组中两个元素的情况。我发现使用嵌套循环的逻辑非常简单,但这可能不是Ru​​by的好用。

对于前。确定数组是否有任何一对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] ...

有人能为这样的问题提供更好的方法吗?

4 个答案:

答案 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 }

其中kv代表&#34; key&#34;和&#34;值&#34;,但由于k未在块计算中使用,因此通常的做法是将k替换为局部变量_(是的,它&#39} ;一个变量 - 在IRB中尝试它,主要是为了告知读者该块中没有使用该参数。

如果arr = [1, 1, -1, -1, 2, -2],则会返回[1,2]。如果您希望它返回[1,1,2],您必须采取不同的方法。