【问题标题】:Compare two arrays containing "/" and keep common elements比较两个包含“/”的数组并保留共同元素
【发布时间】:2017-06-19 12:10:51
【问题描述】:

我正在尝试比较两个包含“/”元素的数组,“/”表示“或”。生成的 Array_3 应由 Array_2 中的 Array_1 元素组成。

Array_1 = ["A", "B", "C/D"]

Array_2 = ["B/Z", "C/D/E"]

对于上述情况,Array_3 应该是 [B, C/D] 因为 B 是 B/Z(B 或 Z)的一部分,而 C/D(C 或 D)是 C/D/E 的一部分(C 或D 或 E)。

Array_3 = Array_1 & Array_2 在这种情况下显然不起作用。此外,.split ("/") 不起作用,因为带有“/”的元素会被分解 - 我想保留带有“/”的原始元素。

【问题讨论】:

  • 这些不是有效的 ruby​​ 数组。 究竟你有什么?
  • 感谢您指出这一点!它们都是字符串值。编辑@SergioTulentsev
  • 如果Array_1"C/F",那么Array_3 应该包含什么?
  • @MarkThomas 在这种情况下,Array_3 应该包含“C/F”,因为“C/D”(C 或 D)是“C/D/E”(C 或 D 或E) - “C”是通用元素。

标签: ruby-on-rails arrays ruby


【解决方案1】:

您可以拆分 Array_2 字符串并将它们放在一个集合中。您只需要遍历Array_1 的每个元素,查看set_2 中是否包含任何字符串:

Array_1 = ["A", "B", "C/D"]
Array_2 = ["B/Z", "C/D/E"]

require 'set'

set_2 = Array_2.flat_map { |s| s.split('/') }.to_set
# <Set: {"B", "Z", "C", "D", "E"}>

p Array_1.select { |s| s.split('/').any? { |letter| set_2.include?(letter) } }
# ["B", "C/D"]

使用Set 仅仅是因为Set#include?Array#include? 快得多,并且include? 被多次使用。

【讨论】:

  • 没有to_set得到相同的结果,那么使用set的目的是什么
  • @GaganGami:Set#include?Array#include? (O(n)) 快得多 (O(1))。如果我必须多次调用include?,我通常更喜欢set 变体。不过你是对的,数组变体也可以工作。
  • 是的,但to_set 是 (O(n))。最好是从创建一个 Set 开始,而不是求助于将 Array 转换为 Set (除非您进行查找的频率远高于转换)
  • @MarkThomas: to_set 是 O(n) 但它只被调用一次。 Array#include? 每次都是 O(n)。如果Array_1m 元素并且Array_2n 元素,这就是O(m+n) 和O(m*n) 之间的区别。直接构建一个集合不会改变算法的复杂性,但它会增加几行。
  • @EricDuminil :感谢人的描述,我对此一无所知
猜你喜欢
  • 2020-06-04
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
  • 2016-06-19
相关资源
最近更新 更多