检查数组并实现bool方法

时间:2014-04-16 01:41:31

标签: ruby arrays boolean

你有一个阵列。如果数组中任何两个数字加零,则返回true。只要有一对加零,返回true并不重要。如果存在零,则只有多个时才能返回true

我写了两个函数,一个用于检查每个函数,最后一个用于组合两者,如果不满足则返回false

def checkZero(array)
  zerocount = 0
  for j in 0..array.count
    if array[j] == 0
      zerocount += 1
    end
  end
  if zerocount > 1 #this part seems to not be working, not sure why
    return true
  else
    return false
  end
end

def checkNegative(array)
  for j in 0..array.count
    neg = -array[j] #set a negative value of the current value
    if array.include?(neg) #check to see whether the negative exists in the array
      return true
    else
      return false
    end
  end
end

def checkArray(array)
  if checkZero(array) == true or checkNegative(array) == true
    return true
  else
    return false
  end
end

然后运行类似

的内容
array = [1,2,3,4,0,1,-1]
checkArray(array)

到目前为止,Ruby还没有回复任何东西。我只是得到一个空白。我有一种感觉return是对的。

4 个答案:

答案 0 :(得分:2)

问题可能是您没有输出结果。

array = [1,2,3,4,0,1,-1]
puts checkArray(array)

如果性能(O( n ^ 2))不是一个很大的问题,checkArray方法可以写成如下所示:

def check_array(array)
  array.combination(2).any?{|p| p.reduce(:+) == 0}
end

效率更高(O( n log n ))解决方案是:

def check_array(array)
  array.sort! # `array = array.sort` if you need the original array unchanged
  i, j = 0, array.size - 1
  while i < j
    sum = array[i] + array[j]
    if sum > 0
      j -= 1
    elsif sum < 0
      i += 1
    else
      return true
    end
  end
  return false
end

答案 1 :(得分:2)

这里有一些相对有效的方法来检查两个值是否总和为零:

解决方案#1

def checkit(a)
  return true if a.count(&:zero?) > 1
  b = a.uniq.map(&:abs)
  b.uniq.size < b.size
end

解决方案#2

def checkit(a)
  return true if a.sort_by(&:abs).each_cons(2).find { |x,y| x == -y }
  false
end

解决方案#3

def checkit(a)
  return true if a.count(&:zero?) > 1
  pos, non_pos = a.group_by { |n| n > 0 }.values
  (pos & non_pos.map { |n| -n }).any?
end

解决方案#4

require 'set'

def checkit(a)
  a.each_with_object(Set.new) do |n,s|
    return true if s.include?(-n)
    s << n
  end
  false
end        

<强>实施例

checkit([1, 3, 4, 2, 2,-3,-5,-7, 0, 0]) #=> true
checkit([1, 3, 4, 2, 2,-3,-5,-7, 0])    #=> true 
checkit([1, 3, 4, 2,-3, 2,-3,-5,-7, 0]) #=> true
checkit([1, 3, 4, 2, 2,-5,-7, 0])       #=> false

<强>说明

以下全部引用数组:

a = [1,3,4,2,2,-3,-5,-7,0]

<强>#1

Zeroes存在一些问题,所以让我们首先看看是否有多个问题,在这种情况下我们已经完成了。由于a.count(&:zero?) #=> 1a.count(&:zero?) > 1 #=> false,所以

return true if a.count(&:zero?) > 1

不会让我们回来。接下来,我们删除所有重复项:

a.uniq                #=> [1, 3, 4, 2, -3, -5, -7, 0]

然后将所有数字转换为其绝对值:

b = a.uniq,map(&:abs) #=> [1, 3, 4, 2,  3,  5,  7, 0]

最后看看c是否包含任何重复项,这意味着原始数组包含至少两个符号相反的非零数字:

c.uniq.size < c.size  #=> true

<强>#2

b = a.sort_by(&:abs)
  #=> [0, 1, 2, 2, 3, -3, 4, -5, -7]

c = b.each_cons(2)
  #=> #<Enumerator: [0, 1, 2, 2, 3, -3, 4, -5, -7]:each_cons(2)>

要查看枚举器的内容:

c.to_a
  #=> [[0, 1], [1, 2], [2, 2], [2, 3], [3, -3], [-3, 4], [4, -5], [-5, -7]]

c.find { |x,y| x == -y }
  #=> [3, -3]

返回如此真实。

<强>#3

return true if a.count(&:zero?) > 1
  #=> return true if 1 > 1

h = a.group_by { |n| n > 0 }
  #=> {true=>[1, 3, 4, 2, 2], false=>[-3, -5, -7, 0]} 
b = h.values 
  #=> [[1, 3, 4, 2, 2], [-3, -5, -7, 0]] 
pos, non_pos = b
pos
  #=> [1, 3, 4, 2, 2]
non_pos
  #=> [-3, -5, -7, 0]
c = non_pos.map { |n| -n }
  #=> [3, 5, 7, 0] 
d = pos & c
  #=> [3] 
d.any?
  #=> true 

<强>#4

require 'set'

enum = a.each_with_object(Set.new)
  #=> #<Enumerator: [1, 3, 4, 2, 2, -3, -5, -7, 0]:each_with_object(#<Set: {}>)>
enum.to_a
  #=> [[1, #<Set: {}>],
  #    [3, #<Set: {}>],
  #    ...
  #    [0, #<Set: {}>]]

将值传递到块中,分配给块变量并执行块,如下所示:

n, s = enum.next
  #=> [1, #<Set: {}>] 
s.include?(-n)
  #=> #<Set: {}>.include?(-1)
  #=> false
s << n
  #=> #<Set: {1}>

n, s = enum.next
  #=> [3, #<Set: {1}>] 
s.include?(-3)
  #=> false 
s << n
  #=> #<Set: {1, 3}> 

...

n, s = enum.next
  #=> [2, #<Set: {1, 3, 4, 2}>] 
s.include?(-n)
  #=> false 
s << n
  #=> #<Set: {1, 3, 4, 2}> # no change

n, s = enum.next
  #=> [-3, #<Set: {1, 3, 4, 2}>] 
s.include?(-n)
  #=> true 

导致true返回。

答案 2 :(得分:1)

我无法重现您的代码的任何问题,但您可以使用combination非常简洁地表达解决方案以获取所有可能的对,然后将每对与reduce求和,最后检查是否有是zero?

[1,2,3,4,0,1,-1].combination(2).map { |pair| pair.reduce(:+) }.any?(&:zero?)

答案 3 :(得分:1)

这有点code review。让我们从第一种方法开始:

def checkZero(array)

Ruby命名约定是snake_case而不是camelCase。这应该是def check_zero(array)

现在循环:

  zerocount = 0
  for j in 0..array.count
    if array[j] == 0
      zerocount += 1
    end
  end

正如@AndrewMarshall所说,for不是惯用的。 each更可取。但是,在ruby中,在ArrayEnumerable(包含在Array中)中可用的所有方法几乎不需要在循环之前初始化变量。我强烈建议将这些方法提交到内存中。以上可以写

array.any? {|number| number.zero?}

或等效

array.any?(&:zero?)

现在,这部分:

  if zerocount > 1 #this part seems to not be working, not sure why
    return true
  else
    return false
  end
end

每当你有模式

if (expr that returns true or false)
  return true
else
  return false
end

它可以简化为return (expr that returns true or false)。如果它是方法的最后一个语句,你甚至可以省略return

全部放在一起:

def check_zero(array)
  array.any?(&:zero?)
end

def check_zero_sum(array)
  array.combination(2).any?{|a,b| a + b == 0}
end

def check_array(array)
  check_zero(array) || check_zero_sum(array)
end

(注意我借用了Andrew check_zero_sum的AndrewMarshall代码,我觉得这很容易理解,但@ CarySwoveland的回答会更快)

修改

我错过了check_zero甚至不需要的事实,因为你至少需要一对,在这种情况下check_zero_sum就是你所需要的。

def check_array(array)
  array.combination(2).any?{|a,b| a + b == 0}
end