Ruby 如何插值数组?

Ruby 如何插值数组?,ruby,arrays,ruby-1.9,Ruby,Arrays,Ruby 1.9,我想用数组执行连接之类的操作,但我想得到的不是字符串,而是数组。我将其称为interpolate。例如,假设: a = [1, 2, 3, 4, 5] 我期望: a.interpolate(0) # => [1, 0, 2, 0, 3, 0, 4, 0, 5] a.interpolate{Array.new} # => [1, [], 2, [], 3, [], 4, [], 5] 得到这个最好的方法是什么?我需要它来获取块的原因是,当我将它用于块时,我希望中间的每个插值器都

我想用
数组
执行
连接
之类的操作,但我想得到的不是
字符串
,而是
数组
。我将其称为
interpolate
。例如,假设:

a = [1, 2, 3, 4, 5]
我期望:

a.interpolate(0) # => [1, 0, 2, 0, 3, 0, 4, 0, 5]  
a.interpolate{Array.new} # => [1, [], 2, [], 3, [], 4, [], 5]
得到这个最好的方法是什么?我需要它来获取块的原因是,当我将它用于块时,我希望中间的每个插值器都有不同的实例


在从许多人那里得到了很好的答案后,我提出了一些修改后的答案

这是对tokland答案的修改。对于
cong1
,我让它接受
nil
。并且还将
if cong2
条件移动到
flat\u map
循环之外,以使其更快

class Array
    def interpolate conj1 = nil, &conj2
        return [] if empty?
        if conj2 then first(length - 1).flat_map{|e| [e, conj2.call]}
        else          first(length - 1).flat_map{|e| [e, conj1]}
        end << last
    end
end
在基准测试之后,第二个看起来更快。看起来,平面地图虽然看起来很漂亮,但速度却很慢。

这里有一种方法:

theArray.map {|element| [element, interpolated_obj]}.flatten
使用:


我不太确定你想对一个区块做什么,但我会这样做:

class Array
  def interpolate(sep)
    h, *t = self
    t.empty? ? [h] : t.inject([h]) { |a, e| a.push(sep, e) }
  end
end
更新:

基准测试(数组大小=100):

实际上我有点惊讶,我以为
zip
会更快

更新2:


zip
更快,
flatte
则不然。

有很多方法可以做到这一点。例如(Ruby 1.9):

(我使用Haskell函数名:)

这里有一个简单的版本(它可以处理多个值和/或一个块),使用
平面映射和
每个控件

class Array
  def interpolate *values
    each_cons(2).flat_map do |e, _|
      [e, *values, *(block_given? ? yield(e) : [])]
    end << last
  end
end

[1,2,3].interpolate(0, "") # => [1, 0, "", 2, 0, "", 3]
[1,2,3].interpolate(&:even?) # => [1, false, 2, true, 3]
类数组
def插值*值
每个都有(2)个平面图_|
[e,*值,*(给定区块??收益率(e):[])]
结束[1,0,”,2,0,”,3]
[1,2,3]。插值(&:偶数?)#=>[1,false,2,true,3]
另一种方法

class Array
  def interpolate(pol=nil)
    new_ary = self.inject([]) do |memo, orig_item|
      pol = yield if block_given?
      memo += [orig_item, pol]
    end
    new_ary.pop
    new_ary
  end
end

[1,2,3].interpolate("A")
#=> [1, "A", 2, "A", 3]

[1,2,3].interpolate {Array.new}
#=> [1, [], 2, [], 3]
这就是它的位置:

class Array
  def interpolate(t = nil)
    each_with_index do |e, i|
      t = yield if block_given?
      insert(i, t) if i % 2 == 1
    end
  end
end

这是因为
t
插入到具有当前索引的元素之前,这使得刚刚插入的
t
成为具有当前索引的元素,这意味着迭代可以正常继续。

为什么使用
数组的块。新建
?你不能把它作为一个参数传递吗?@Linux_iOS.rb.cpp.c.lisp.m.sh也许我的例子不好,但有时,我需要每个插值器的不同实例。这很有意义。这意味着我的答案一文不值。抱歉。您将使用
插值_obj
作为结果的最后一个元素,这看起来不像是期望的行为。在我的系统上,它产生
[[1,0],[2,0],[3,0]]
这与期望的输出相差甚远:-)我想您忘记了
。展平(1)[0…-1]
,此外,它还创建了一个新的阵列,而实际上你的想法看起来不错。我将你的答案与维克多·莫洛兹的答案进行比较,想知道哪个更快。“想知道哪个更快”,不要想知道,基准!但是,考虑到
zip
是用C写的,我会认为它更快。。。除非您有足够大的数据集并观察到问题,否则不要担心它。关注代码可读性,如果速度减慢,使用分析工具和基准测试跟踪瓶颈。我喜欢你关于
h,*t=self
,但是
inject
不是很重吗?我想知道你的答案与创建数组和压缩类似于Lucapete的答案之间哪个更快。看起来你的答案非常快。谢谢你的基准测试。这看起来不错。我正在把这个和其他答案进行比较。谢谢。这与我想要的非常接近。我想你可以将
返回
条件放宽到
if self.empty?
@sawa,编辑某人的答案被认为是不好的形式。您可以编辑您的问题以附加您的版本,也可以向他们的问题添加注释。答案的编辑应该是拼写、格式、可读性等,但代码应该是神圣不可侵犯的。@sawa:确实,使用“空”编辑。我真的不介意你编辑了这个问题,但铁皮人是对的,最好创建一个单独的答案。我喜欢它的美丽或你的代码,但经过密集的基准测试后,Victor Moroz的答案加上允许proc的修改似乎是最快的。谢谢。我认为你的答案是优越的,因为它允许
pol
使用
nil
。但是我有点担心
inject
可能很重。我做了基准测试,看起来
+=
很重<代码>注入
不可用。
class Array
  def interpolate(sep)
    h, *t = self
    t.empty? ? [h] : t.inject([h]) { |a, e| a.push(sep, e) }
  end
end
            user     system      total        real
inject  0.730000   0.000000   0.730000 (  0.767565)
zip     1.030000   0.000000   1.030000 (  1.034664)
class Array
  def intersperse(item = nil)
    return clone if self.empty?
    take(self.length - 1).flat_map do |x|
      [x, item || yield]
    end + [self.last]
  end
end

p [].intersperse(0)
#=> []

p [1, 2, 3, 4, 5].intersperse(0)
#= >[1, 0, 2, 0, 3, 0, 4, 0, 5]

p [1, 2, 3, 4, 5].intersperse { 0 }
#= >[1, 0, 2, 0, 3, 0, 4, 0, 5]
class Array
  def interpolate *values
    each_cons(2).flat_map do |e, _|
      [e, *values, *(block_given? ? yield(e) : [])]
    end << last
  end
end

[1,2,3].interpolate(0, "") # => [1, 0, "", 2, 0, "", 3]
[1,2,3].interpolate(&:even?) # => [1, false, 2, true, 3]
class Array
  def interpolate(pol=nil)
    new_ary = self.inject([]) do |memo, orig_item|
      pol = yield if block_given?
      memo += [orig_item, pol]
    end
    new_ary.pop
    new_ary
  end
end

[1,2,3].interpolate("A")
#=> [1, "A", 2, "A", 3]

[1,2,3].interpolate {Array.new}
#=> [1, [], 2, [], 3]
class Array
  def interpolate(t = nil)
    each_with_index do |e, i|
      t = yield if block_given?
      insert(i, t) if i % 2 == 1
    end
  end
end