如何用each_slice拆分数组并保留衔接值(单行实现)
解决Ruby数组转首尾衔接线段数组(单行实现+返回父对象)
嘿,这个问题的核心是找对Ruby的Enumerable方法!你之前用each_slice拆分数组没错,但要实现首尾衔接的线段配对,each_cons才是你需要的神器——它会从集合里取出连续的n个元素,正好能让前一个线段的终点变成下一个线段的起点。
第一步:单行实现数组格式转换
先搞定数组的格式转换,用flat_map+each_slice+each_cons就能一步到位:
full_line_coords = [[1, 1, 2, 2, 3, 3, 4, 4], [5, 5, 6, 6, 7, 7, 8, 8]] desired = full_line_coords.flat_map { |arr| arr.each_slice(2).to_a.each_cons(2).to_a } # 输出结果: # [[[1, 1], [2, 2]], [[2, 2], [3, 3]], [[3, 3], [4, 4]], [[5, 5], [6, 6]], [[6, 6], [7, 7]], [[7, 7], [8, 8]]]
arr.each_slice(2).to_a:把一维坐标数组拆成单个点的数组,比如[1,1,2,2,...]变成[[1,1],[2,2],[3,3],[4,4]]each_cons(2):从点数组里取连续的2个点,组合成线段,比如[[1,1],[2,2]]、[[2,2],[3,3]]flat_map:把多个子数组的处理结果合并成一个大数组,避免嵌套层级
第二步:修改Link对象并返回父对象本身
要保留Link实例本身(而不是只返回处理后的segments),用Ruby的tap方法就可以——它会执行块内的修改逻辑,然后返回原对象/数组。
如果要批量处理所有Link对象,同时返回原始的links数组:
# 修改每个link的segments属性,最终返回links本身 links.tap { |link_list| link_list.each { |link| link.segments = link.segments.each_slice(2).to_a.each_cons(2).to_a } }
如果是单独处理单个Link对象:
# 修改单个link的segments,返回该link实例 link.tap { |l| l.segments = l.segments.each_slice(2).to_a.each_cons(2).to_a }
这样既完成了segments的格式转换,又能返回你需要的父对象(Link实例或其列表),完美符合你的需求~
内容的提问来源于stack exchange,提问作者rpg
相关产品推荐
相关产品推荐

