根据属性执行两个数组的交集并返回对象

3

我有两个数组,都装满了具有许多属性的对象。这两个数组都包含相同类型的对象。我想根据它们的属性id找到对象匹配的位置。

对象示例:

#<Link:0x00007fac5eb6afc8 @id = 2002001, @length=40, @area='mars' ...>

填充对象的示例数组:

array_links = [<Link:0x00007fac5eb6afc8>, <Link:0x00007fdf5eb7afc2>, <Link:0x000081dag6zb7agg8>... ]
selected_links = [<Link:0x00007fad8ob6gbh5>, <Link:0x00007fdg7hh4tif4>, <Link:0x000081dag7ij5bhh9>... ]

如果这些是对象ID的字符串,并且有匹配项,我可以使用以下代码:
intersection = array_links & selected_links

然而,我想基于它们的属性来执行此操作,并返回匹配的对象本身。就像这样:
intersection = array_links.select(&:id) & selected_links.select(&:id)

当然,不是那个,因为那样行不通,有什么想法? :)

它们是否应该是相同的?还是仅基于它们的id属性? - Sebastián Palma
基于它们的ID。实际上,两个数组中会有一些相同的对象,但是它们已经被赋予不同的对象ID,因此我需要使用它们的属性来查找匹配项,并返回对象本身(从任何一个数组中)。 - rpg
请参见以下链接:https://dev59.com/j2ox5IYBdhLWcg3w3YD- - Sebastián Palma
array_links.select(&:id) & selected_links.select(&:id) 应该会返回一个数组,其中包含两个数组中都存在的 id。当然,这意味着你的 Link 对象理解 _id_ 方法。你认为它为什么不起作用呢? - user1934428
1
在这种情况下,select(&:id)听起来很奇怪,因为它所做的只是收集那些id返回值为真实的元素,它似乎与所述问题无关。 - Sebastián Palma
2个回答

1

您可以:

1 :

重写eql?(other)方法,然后数组交集将起作用

class Link < ApplicationRecord
  def eql?(other)
    self.class == other.class && self.id == other&.id # classes comparing class is a guard here
  end
  
  # you should always update the hash if you are overriding the eql?() https://dev59.com/orLma4cB1Zd3GeqPXz0e#54961965
  def hash
    self.id.hash
  end 
end

2:

使用array.select

array_links.flat_map {|i| selected_links.select {|k|  k.user_id == i.user_id }}

1
@EricDuminil 好观点,谢谢,已更新答案。 - Mshka

1
如果它们在内存中是相同的对象,即array_links = [<Link:0x123]selected_links = [<Link:0x123>],那么您的解决方案为:
intersection = array_links & selected_links

应该可以工作。

如果不行,您可以循环遍历您的array_links选择那些在selected_links中的链接:

intersection = array_links.select do |link|
  link.id.in? selected_links.map(&:id)
end 

如果您循环遍历selected_links并选择array_links中的链接,则结果将相同。根据您的资源和这些数组的大小,您可以记忆selected_links.map(&:id)以防止在每次迭代时重建它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接