Ruby中如何简化数组元素方向交替性的检查逻辑?
简化交替数组检查的几种方案
你的代码逻辑可行,但存在边界情况处理缺失(比如数组长度≤2时会错误返回false),同时可以通过更贴合问题语义的写法提升可读性和简洁度。以下是几种优化方案:
方案一:基于符号交替的简化写法
合并原代码中的冗余map操作,同时修复边界问题,逻辑更紧凑:
def alternating?(array) return true if array.size <= 2 signs = array.each_cons(2).map { |a, b| b <=> a } signs.each_cons(2).all? { |s1, s2| s1 == -s2 } end
- 用
b <=> a直接得到相邻元素的增减符号(1代表递增,-1代表递减) - 用
all?替代原代码的map+uniq==[0],直接判断所有相邻符号是否互为相反数,语义更清晰 - 补充了数组长度≤2的边界处理(这类数组天然满足交替条件)
方案二:直接贴合问题语义的写法(最易读)
问题的核心是每个中间元素要么是局部峰值(比左右都大),要么是局部谷值(比左右都小),直接基于这个逻辑实现:
def alternating?(array) array.size <= 2 || array.each_cons(3).all? do |a, b, c| (b > a && b > c) || (b < a && b < c) end end
- 用
each_cons(3)直接遍历所有连续三元组,无需计算中间符号 - 代码逻辑完全对应问题描述,可读性拉满,一眼就能理解要做什么
- 自动处理了重复元素的情况(比如
[1,2,2,1,3]中的连续2,会因为不满足峰/谷条件直接返回false)
方案三:极致紧凑的链式写法
如果追求代码简洁,可以把方案一的逻辑压缩成一行链式调用:
def alternating?(array) array.size <= 2 || array.each_cons(2).map { |a,b| b <=> a }.each_cons(2).all? { |s1,s2| s1 == -s2 } end
测试验证
用你给出的测试用例验证:
alternating?([1,3,2,4,3]) # => true alternating?([3,2,4,3,5]) # => true alternating?([1,2,3,1,3]) # => false alternating?([1,2,2,1,3]) # => false alternating?([1,2]) # => true(修复了原代码的边界问题)
内容的提问来源于stack exchange,提问作者Sig
相关产品推荐
相关产品推荐

