You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SketchUp Ruby编程:提取数组中匹配与不匹配的Point3d元素

Ruby数组按Point3d对象匹配筛选解决方案

问题描述

需要处理两个包含Point3d对象的Ruby数组,目标是:

  • 从数组a中筛选出Point3d在数组b中存在的子数组(即result_match)
  • 从数组b中筛选出Point3d不在数组a中存在的子数组(即result_non_match)

尝试过samepoint = a.map(&:to_a) & b.map(&:to_a)但未成功。

输入示例

a = [['xxx', [0.203125, 0.203125, 0.0], 
      Point3d(12, 1.25984, -0.275591), nil], 
     ['eee', [0.203125, 0.203125, 0.0], 
      Point3d(12, 20.0995, -0.275591), nil]]

b = [['aaa', [0.203125, 0.203125, 0.0], 
      Point3d(10, 1.25984, -0.275591), nil], 
     ['sss', [0.203125, 0.203125, 0.0], 
      Point3d(10, 20.0995, -0.275591), nil], 
     ['www', [0.203125, 0.203125, 0.0], 
      Point3d(12, 1.25984, -0.275591), nil], 
     ['nnn', [0.203125, 0.203125, 0.0], 
      Point3d(12, 20.0995, -0.275591), nil]]

失败原因分析

直接使用map(&:to_a)后取交集的方法失效,通常有两个原因:

  1. Point3d对象的相等性判断:默认情况下Ruby对象的==比较内存地址,而非坐标值。即使to_a返回坐标数组,若Point3d未正确实现to_a方法,也无法生成可比较的坐标数组。
  2. 浮点数精度问题:坐标中的浮点数可能存在微小精度差异,直接比较数组会导致匹配失败。

解决方案

前提假设

假设你使用的Point3d类(比如SketchUp的Point3d)已实现按坐标值判断相等的==方法,或可以通过to_a返回包含x/y/z坐标的数组。

代码实现

1. 筛选匹配的子数组(result_match)

先提取数组b中的所有Point3d对象存入集合(集合查找效率更高),再从a中筛选符合条件的子数组:

require 'set'

# 提取b中所有Point3d对象,存入集合
b_points = Set.new(b.map { |sub_arr| sub_arr[2] })

# 从a中筛选Point3d存在于b_points的子数组
result_match = a.select { |sub_arr| b_points.include?(sub_arr[2]) }

2. 筛选不匹配的子数组(result_non_match)

提取数组a中的所有Point3d对象存入集合,再从b中排除符合条件的子数组:

require 'set'

# 提取a中所有Point3d对象,存入集合
a_points = Set.new(a.map { |sub_arr| sub_arr[2] })

# 从b中筛选Point3d不存在于a_points的子数组
result_non_match = b.reject { |sub_arr| a_points.include?(sub_arr[2]) }

处理浮点数精度问题

如果存在浮点数精度差异导致匹配失败,可以将坐标值四舍五入后再比较:

require 'set'

# 提取b中Point3d的坐标数组(四舍五入到5位小数)
b_coords = Set.new(b.map { |sub_arr| 
  sub_arr[2].to_a.map { |num| num.round(5) }
})

# 筛选匹配的子数组
result_match = a.select { |sub_arr| 
  coords = sub_arr[2].to_a.map { |num| num.round(5) }
  b_coords.include?(coords)
}

# 提取a中Point3d的坐标数组
a_coords = Set.new(a.map { |sub_arr| 
  sub_arr[2].to_a.map { |num| num.round(5) }
})

# 筛选不匹配的子数组
result_non_match = b.reject { |sub_arr| 
  coords = sub_arr[2].to_a.map { |num| num.round(5) }
  a_coords.include?(coords)
}

验证结果

运行上述代码后,将得到期望输出:

  • result_match为数组a的两个子数组(其Point3d在b中存在)
  • result_non_match为数组b的前两个子数组(其Point3d不在a中存在)

内容的提问来源于stack exchange,提问作者JoMojo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:05:23