Select 个基于属性的唯一对象

Select unique objects based on an attribute

我有一个对象数组,每个对象都有一个起点和一个终点。每个起点或终点都有一个名称和一个点。我想 return 基于名称的唯一起点-目的地对。例如,在下面的数组中:

[
  obj1,
  obj2,
  obj3,
  obj4
]

哪里

obj1 = (o1=(name: "name 1", point: "x1, y1"), d1=(name: "name 3", point: "x2, y2"))
obj2 = (o2=(name: "name 2", point: "x3, y3"), d2=(name: "name 4", point: "x4, y4"))
obj3 = (o3=(name: "name 1", point: "x5, y5"), d3=(name: "name 3", point: "x6, y6"))
obj4 = (o4=(name: "name 2", point: "x7, y7"), d4=(name: "name 4", point: "x8, y8"))

obj1 被认为与 obj3 相同,因为 obj1.o1.name = obj3.o3.name 和 obj1.d1.name = obj3.d3.name。同样,obj2 和 obj4 是相同的。我如何才能 return 仅从上面的数组中获取 obj1(或 obj2)和 obj3(或 obj4)?

出于唯一性考虑,下面的代码会查看整个起点或终点,但我只需要考虑起点和终点的名称。

my_array.map { |obj| [obj.origin, obj.destination] }
        .uniq

我觉得最好逆向操作先获取唯一对象再映射获取点

Array#uniq 占一格

arr
 .uniq { |obj| obj.name }
 .map { |obj| [obj.origin, obj.destination] }

你也可以使用 shorthand 作为 uniq .uniq(&:name)

uniq 可以拿块

my_array.uniq { |obj| [obj.origin.name, obj.destination.name]}
        .map { |obj| [obj.origin, obj.destination] }

# or

my_array.map { |obj| [obj.origin, obj.destination] }
        .uniq { |pair| pair.map(&:name) } 

您可以使用uniq 来获取uniq 对象。您还可以将块传递给 uniq 以根据您的自定义过滤器获取不同的元素。

文档 link - Array#uniq

所以像这样 -

# Objects initialization
obj1 = { origin: { name: "name 1", point: "x1, y1" }, destination: { name: "name 3", point: "x2, y2"} }
obj2 = { origin: { name: "name 2", point: "x3, y3" }, destination: { name: "name 4", point: "x4, y4" }}
obj3 = { origin: { name: "name 1", point: "x5, y5" }, destination: { name: "name 3", point: "x6, y6"} }
obj4 = { origin: { name: "name 2", point: "x7, y7" }, destination: { name: "name 4", point: "x8, y8" }}

my_array = [obj1, obj2, obj3, obj4]

# Now to get distinct by just origin name
my_array.uniq { |obj| obj[:origin][:name] }
#=> [obj1, obj2]

# To get distinct by origin name and destination name
# You can create an array of both names in uniq block
my_array.uniq { |obj| [obj[:origin][:name], obj[:destination][:name]] }
# => [obj1, obj2]