是否有一个Ruby one-liner-to-join()嵌套Ruby数组,内部/外部数组使用不同的join(()字符串



用于:

a = [ ["John", "Doe"], ["Sue", "Smith"]]

所需输出为:"John Doe, Sue Smith"

暴力代码很简单:

a = [ ["John", "Doe"], ["Sue", "Smith"]]
name_array = []
a.each { |n| name_array << n.join(" ") } # first, inner join w/ space
s = name_array.join(", ") # then, outer join with comma

但是,在Ruby中是否有更简洁的(一行代码?(来实现这一点?

映射并加入

您可以使用Array#map和Array#join来执行此操作。例如,在Ruby 2.7.1:中

array = [["John", "Doe"], ["Sue", "Smith"]]
array.map { _1.join ?s }.join ", "
#=> "John Doe, Sue Smith"

如果你没有使用最新的Ruby,或者发现更明确的语法更可取,你可以做同样的事情:

array.map { |subarray| subarray.join " " }.join ", "
#=> "John Doe, Sue Smith"

当然还有其他方法可以做到这一点,但这一行似乎适合您的示例和用例。

a = [["John", "Doe"], ["Sue", "Smith"], ["Melba", "Jones"]]

其他人提到的显而易见的方法是:

a.map { |arr| arr.join(' ') }.join(', ')
#=> "John Doe, Sue Smith, Melba Jones"

作为练习,这里有三种方法可以在不使用Array#map的情况下完成

使用可枚举#reduce(又名inject(

a.drop(1).reduce(a.first.join(' ')) { |s,name| s + ", %s %s" % name }
#=> "John Doe, Sue Smith, Melba Jones"

使用递归

def doit((name, *rest))
rest.empty? ? name.join(' ') : "%s %s, %s" % [*name, doit(rest)]
end
doit(a)
#=> "John Doe, Sue Smith, Melba Jones"

压扁,用空格连接,使用String#gsub插入逗号

r = /
w+[ ]w+ # match two words separated by a space
(?=[ ])   # positive lookahead asserts that next character is a space
K        # reset start of match to current location and discard all
# previously matched characters from match that is returned
/x        # free-spacing regex definition mode
a.flatten.join(' ').gsub(r, ',')
#=> "John Doe, Sue Smith, Melba Jones"

当您想要从现有数组(或任何可枚举数组(构造新数组时,您真正想要使用的是enumerable#map。

Map在现有数组上迭代,运行块并收集结果。

result = a.map { |people| people.join(' ') }.join(', ')

分解:

intermediate = a.map { |people| people.join(' ') } 
# transforms
#   [ ["John", "Doe"], ["Sue", "Smith"]]
# into
#   [ "John Doe", "Sue Smith" ]
# we take the result of that and run
result = intermediate.join(', ')
# which then transforms your array in the the final string:
# "John Doe, Sue Smith"

最新更新