Array question

Need to take care of size == 1

 class Array
  def duplicate_internal
    return self if size == 1 # added
    to_enum(:each_cons,2).inject([]) do |r, c|
      r + c
    end
  end
end

Hi –

On Wed, 22 Nov 2006, Pete Y. wrote:

I’m surprised nobody has suggested:

a.zip(a).flatten[1…-2]

I decided to avoid flatten (see my earlier comments). To be
flatten-safe, you could do:

require ‘flattenx’ # [1]
a.zip(a).flatten_once[1…-2]

David

[1] http://www.rubypal.com/ruby/flattenx

Pete Y. [mailto:[email protected]] :

I’m surprised nobody has suggested:

a.zip(a).flatten[1…-2]

indeed. that’s a nice surprise. thanks for the tip.
kind regards -botp

Cheers,

Pete Y.

On Wed, 2006-11-22 at 07:36 +0900, Pete Y. wrote:

I’m surprised nobody has suggested:

a.zip(a).flatten[1…-2]

I’m surprised nobody has suggested

require ‘enumerator’

ary.enum_cons(2).entries.flatten

Cheers,
Daniel

Li Chen wrote:

Hi all,

I want to build a new array from an old one with every element being
duplicated except the first and last element. And here are my codes. I
wonder if this is a real Ruby way to do it.

array=[1,2,3,4,5,6,7,8,9,10]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

array.zip(array).flatten[1…-2]
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

On 21.11.2006 08:18, William J. wrote:

=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]
That’s cute! I have another one with #inject (of course):

irb(main):007:0> arr=(1…10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):008:0> copy=[]
=> []
irb(main):009:0> arr.inject{|a,b| copy << a << b; b}
=> 10
irb(main):010:0> copy
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

Kind regards

robert

On 21.11.2006 10:16, William J. wrote:

array.zip(array).flatten[1…-2]
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

This demonstrates an excellent understanding of inject and

Thank you!

is a good way to eliminate the somewhat ugly [1…-2].

Well, you can use [1…-1] instead. :slight_smile:

Here’s a prolix way of avoiding array indexing while using zip:

copy=arr.dup; copy.shift; copy.pop
arr.zip(copy).flatten.compact

You can copy and reduce in one step:

arr=(1…10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

arr.zip(arr[1…-1]).flatten.compact
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

Or, more efficient

arr.zip(arr[1…-1]).flatten!.compact!
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

Cheers

robert

Hi –

On Thu, 23 Nov 2006, William J. wrote:

array.zip(array).flatten[1…-2]
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

I still don’t feel comfortable with that one :slight_smile: The flatten
thing is just too fragile.

David

Robert K. wrote:

array.zip(array).flatten[1…-2]
irb(main):010:0> copy
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

Kind regards

robert

This demonstrates an excellent understanding of inject and
is a good way to eliminate the somewhat ugly [1…-2].

Here’s a prolix way of avoiding array indexing while using zip:

copy=arr.dup; copy.shift; copy.pop
arr.zip(copy).flatten.compact

Robert K. wrote:

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):010:0> copy
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

This demonstrates an excellent understanding of inject and

Thank you!

is a good way to eliminate the somewhat ugly [1…-2].

Well, you can use [1…-1] instead. :slight_smile:

Ha, ha. Also ugly.

arr.zip(arr[1…-1]).flatten.compact
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

Or, more efficient

arr.zip(arr[1…-1]).flatten!.compact!
=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

But it has “[1…-1]”! Indexing with literal numbers is so horrid.

On 11/22/06, Daniel S. [email protected] wrote:

On Wed, 2006-11-22 at 07:36 +0900, Pete Y. wrote:

I’m surprised nobody has suggested:

a.zip(a).flatten[1…-2]

I’m surprised nobody has suggested

require ‘enumerator’

ary.enum_cons(2).entries.flatten

ary.enum_cons(2).inject([]) {|a, i| a+i}

martin

I benchmarked the various suggestions and added some of my own, and the
results may surprise some (they surprised me!)

Rehearsal --------------------------------------------------------------
:zip_flatten_technique 8.280000 0.000000 8.280000 ( 19.532383)
:enum_cons_technique 18.190000 0.020000 18.210000 ( 28.552418)
:copy_inject_technique 5.500000 0.000000 5.500000 ( 5.567597)
:fill_technique 5.250000 0.010000 5.260000 ( 5.373526)
:naive_technique 5.040000 0.000000 5.040000 ( 5.091017)
:flatten_compact_technique 7.900000 0.000000 7.900000 ( 7.938109)
:original_technique 2.560000 0.000000 2.560000 ( 2.620933)
:zip_concat_technique 6.480000 0.000000 6.480000 ( 6.493874)
---------------------------------------------------- total: 59.230000sec

                             user     system      total        real

:zip_flatten_technique 7.500000 0.000000 7.500000 ( 7.636382)
:enum_cons_technique 17.790000 0.680000 18.470000 ( 18.536960)
:copy_inject_technique 5.250000 0.000000 5.250000 ( 5.277144)
:fill_technique 5.070000 0.010000 5.080000 ( 5.165221)
:naive_technique 5.100000 0.010000 5.110000 ( 5.113858)
:flatten_compact_technique 7.330000 0.000000 7.330000 ( 7.350595)
:original_technique 2.590000 0.000000 2.590000 ( 2.600783)
:zip_concat_technique 6.190000 0.000000 6.190000 ( 6.197641)

So the OP’s technique, if not the prettiest, is actually by far the
fastest, and is correct when used with nested arrays. Some of the other
solutions (that use flatten) are incorrect when used with nested arrays.

Here’s the code:

require ‘benchmark’
require ‘enumerator’

techniques = {
:enum_cons_technique => lambda {|arr|
arr.enum_cons(2).inject([]) {|a, i| a+i}},
:zip_flatten_technique => lambda {|arr|
arr.zip(arr).flatten[1…-2]},
:copy_inject_technique => lambda {|arr| copy = [];
arr.inject{|a,b| copy << a << b; b}; copy},
:flatten_compact_technique => lambda {|arr|
arr.zip(arr[1…-1]).flatten!.compact!},
:zip_concat_technique => lambda {|arr| arr.zip(arr).inject([])
{|n, e| n.concat(e)}[1…-2]},
:fill_technique => lambda {|arr| (Array.new((arr.length <<

      1. {|i| arr[i >> 1]})[1…-2]},
        :naive_technique => lambda do |arr|
        a = Array.new((arr.length * 2) - 2)
        a[0] = arr.first
        a[a.length - 1] = arr.last
        n = 1
        1.upto(arr.length - 2) {|i| a[n] =
        a[n+1] = arr[i]; n += 2}
        a
        end,
        :original_technique => lambda do |arr|
        array_new = Array.new
        arr.each {|e| array_new << e << e}
        array_new.delete_at(0)
        array_new.delete_at(array_new.size -
  1.                            array_new
                             end
    

}

n = 5000
array = [“a”, 2, (0…1), /^$/, 1.2345, [“arr”] ] * 100

Benchmark.bmbm do |x|
techniques.each do |name, proc|
x.report(name.inspect) { n.times { proc.call(array) } }
end
end

So the OP’s technique, if not the prettiest, is actually by far the
fastest, and is correct when used with nested arrays. Some of the other
solutions (that use flatten) are incorrect when used with nested arrays.

What is meaning for OP here?

Thanks,

Li

Li Chen wrote:

So the OP’s technique, if not the prettiest, is actually by far the
fastest, and is correct when used with nested arrays. Some of the other
solutions (that use flatten) are incorrect when used with nested arrays.

What is meaning for OP here?

Thanks,

Li

Sorry, OP = original poster (that would be YOU :slight_smile:

On 22-Nov-06, at 6:19 PM, Li Chen wrote:

So the OP’s technique, if not the prettiest, is actually by far the
fastest, and is correct when used with nested arrays. Some of the
other
solutions (that use flatten) are incorrect when used with nested
arrays.

What is meaning for OP here?

Original Poster

Mike S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

2006/11/23, William J. [email protected]:

duplicated except the first and last element. And here are my
irb(main):008:0> copy=[]
is a good way to eliminate the somewhat ugly [1…-2].

=> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]

But it has “[1…-1]”! Indexing with literal numbers is so horrid.

Cheers

  robert

your name looks like a chinese , and i’m too.