我有两个数组
b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
目前我在这两个数组上使用联合运算符,如下所示:a | b
。组合时,即使每个数组中的名称都是“相同”名称(它们只是使用名称的缩写版本),它也会重复我的名字。
我建议的解决方案是简单地选择第一次出现的首字母 + 姓氏作为执行联合的名称,但是,我不记得 Ruby 中有任何方法可以执行这样的操作。
所以 some_method(a | b)
的结果将返回 c
,它只是:
["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
我想知道如何实现这一目标?
最佳答案
b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
r = /
\s # match a space
[[:alpha:]]+ # match > 0 alphabetic characters
\z # match end of string
/x # free-spacing regex definition mode
(b+a).uniq { |str| [str[0], str[r]] }
#=> ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
这使用了方法的形式 Array#uniq使用 block 。
你也可以写成(b|a).uniq { |str| [str[0], str[r]] }
步骤如下。
c = b+a
# => ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas",
# "Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
c
的第一个元素传递给 block 的是
str = c.first
#=> "John Roberts"
所以分块计算是
[str[0], str[r]]
#=> ["J", " Roberts"]
c
的所有其他元素的计算都类似.结果是
c.uniq { |str| [str[0], str[r]] }
相当于选择c
的第一个元素, 当转换为 [<first name initial>, <last name>]
, 匹配数组的一个元素 d
, 其中
d = [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"],
["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]].uniq
#=> [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]]
Pascal 建议 uniq
会更好的 block 返回一个字符串:
{ |str| "#{str[0]} #{str[r]}" }
(例如,"J Roberts"
)可能会被写成
{ |str| str.sub(/(?<=.)\S+/,"") }
第一个首字母后的空格是可选的(例如,"JRoberts"
也可以)。
关于arrays - 使用自定义规则执行两个数组的并集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39172117/