Array question

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.

Thank you for your input.

Li

···

#########
C:\>irb
irb(main):001:0> array=[1,2,3,4,5,6,7,8,9,10]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):002:0> array_new=Array.new
=> []
irb(main):003:0> array.each do |e|
irb(main):004:1* array_new<<"#{e}"
irb(main):005:1> array_new<<"#{e}"
irb(main):006:1> end
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):007:0>
irb(main):008:0* array_new.delete_at(0)
=> "1"
irb(main):009:0> array_new.delete_at(array_new.size-1)
=> "10"
irb(main):010:0> puts array_new
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
=> nil

--
Posted via http://www.ruby-forum.com/.

A couple of ways: (there are probably dozens more)
# given:
array = [1,2,3,4,5,6]

# 1.
new_array = array[1..-2]

# 2.
new_array = array.dup
new_array.shift # shifts off the first element
new_array.pop # pops off the last element

#1 uses Array#, which is a synonym for Array#slice.
1..-2 is a Range parameter. In this case, it says you want a slice of
the array containing everything but the first and last element.

···

On 11/20/06, Li Chen <chen_li3@yahoo.com> 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.

Hi --

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.

Here's one way, along with some tests:

require 'test/unit'

class ChangeArrayTest < Test::Unit::TestCase

   def change_array(a)
     [*1...a.size-1].reverse.each {|i| a.insert(i,a[i]) }
     a
   end

   def test_empty_array
     assert_equal(, change_array())
   end

   def test_one_element_array
     assert_equal([1], change_array([1]))
   end

   def test_two_element_array
     assert_equal([1,2], change_array([1,2]))
   end

   def test_three_element_array
     assert_equal([1,2,2,3], change_array([1,2,3]))
   end

   def test_ten_element_array
     assert_equal([1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10],
     change_array([1,2,3,4,5,6,7,8,9,10]))
   end
end

David

···

On Tue, 21 Nov 2006, Li Chen wrote:

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Li Chen schrieb:

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.
  

c = a.size > 2 ? a[0, 1] + a[1..-2].inject() { |b,x| b << x << (x.dup rescue x) } + a[-1, 1] : a

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]

This would not duplicate the inner elements though.

To build on this one.
b = a.inject( ) { |a,e| a << [e,e]}.flatten[1..-2]

This looks pretty jarring to my eyes though :frowning:

···

On 11/21/06, Wilson Bilkovich <wilsonb@gmail.com> wrote:

>

A couple of ways: (there are probably dozens more)
# given:
array = [1,2,3,4,5,6]

# 1.
new_array = array[1..-2]

Hi --

···

On Tue, 21 Nov 2006, Wilson Bilkovich wrote:

On 11/20/06, Li Chen <chen_li3@yahoo.com> 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.

A couple of ways: (there are probably dozens more)
# given:
array = [1,2,3,4,5,6]

# 1.
new_array = array[1..-2]

# 2.
new_array = array.dup
new_array.shift # shifts off the first element
new_array.pop # pops off the last element

I think Li wanted to duplicate elements in the sense of:

   [1,2,3,4,5] => [1,2,2,3,3,4,4,5]

David

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

A couple of ways: (there are probably dozens more)
# given:
array = [1,2,3,4,5,6]

# 1.
new_array = array[1..-2]

# 2.
new_array = array.dup
new_array.shift # shifts off the first element
new_array.pop # pops off the last element

#1 uses Array#, which is a synonym for Array#slice.
1..-2 is a Range parameter. In this case, it says you want a slice of
the array containing everything but the first and last element.

Hi,

I run array=[1,2,3,4,5]
       new_array = array.dup
       new_array.shift
       new_array.pop
I get [2,3,4] but I want this result [1,2,2,3,3,4,4,5]

Li

···

--
Posted via http://www.ruby-forum.com/\.

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 08:18, William James wrote:

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]

Hi --

···

On Thu, 23 Nov 2006, William James wrote:

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]

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

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

b = a.inject( ) { |a,e| a << [e,e]}.flatten[1..-2] }

···

On 11/21/06, Daniel N <has.sox@gmail.com> wrote:

On 11/21/06, Wilson Bilkovich <wilsonb@gmail.com> wrote:
>
> >
>
> A couple of ways: (there are probably dozens more)
> # given:
> array = [1,2,3,4,5,6]
>
> # 1.
> new_array = array[1..-2]

This would not duplicate the inner elements though.

To build on this one.
b = a.inject( ) { |a,e| a << [e,e]}.flatten[1..-2]

This looks pretty jarring to my eyes though :frowning:

Sorry missed a brace on the block. Should be

Yeah. Sorry. I didn't read your question clearly enough. I apologize
for confusing the issue. Check out the other replies from people with
better reading comprehension late at night.
Heh.

···

On 11/21/06, Li Chen <chen_li3@yahoo.com> wrote:

> A couple of ways: (there are probably dozens more)
> # given:
> array = [1,2,3,4,5,6]
>
> # 1.
> new_array = array[1..-2]
>
> # 2.
> new_array = array.dup
> new_array.shift # shifts off the first element
> new_array.pop # pops off the last element
>
> #1 uses Array#, which is a synonym for Array#slice.
> 1..-2 is a Range parameter. In this case, it says you want a slice of
> the array containing everything but the first and last element.

Hi,

I run array=[1,2,3,4,5]
       new_array = array.dup
       new_array.shift
       new_array.pop
I get [2,3,4] but I want this result [1,2,2,3,3,4,4,5]

Li

Daniel N wrote:

>

A couple of ways: (there are probably dozens more)
# given:
array = [1,2,3,4,5,6]

# 1.
new_array = array[1..-2]

This would not duplicate the inner elements though.

To build on this one.
b = a.inject( ) { |a,e| a << [e,e]}.flatten[1..-2]

This looks pretty jarring to my eyes though :frowning:

I would use map over inject into :

b = a.map { |each| [each,each] }.flatten[1..-2]

Either that, or recognize that it's equivalent duplicating all except first and last.

b = [a[0], a[1..-2].map { |each| [each, each] }.flatten, a[-1]]

In either case, we can avoid the flatten entirely, at the expense of returning to inject:

b = a.inject() {|sum, each| sum.concat([each, each])[1..-2]
or
b = [a[0],
      a[1..-2].inject() {|sum, each| sum.concat([each, each])},
      a[-1]]

Of course, if we know the items in the array are in ascending order, we can /really/ cheat:

b = (a*2).sort[1..-2]

That's as many as I could think of.

···

On 11/21/06, Wilson Bilkovich <wilsonb@gmail.com> wrote:

--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice

On_Behalf_Of_Li_Chen:
# I run array=[1,2,3,4,5]
# new_array = array.dup
# new_array.shift
# new_array.pop
# I get [2,3,4] but I want this result [1,2,2,3,3,4,4,5]

but you can build from there. you just have to assemble it back, something like,

irb(main):031:0> array=[1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):032:0> new_array = array.dup
=> [1, 2, 3, 4, 5]
irb(main):035:0> first = new_array.shift
=> 1
irb(main):036:0> last = new_array.pop
=> 5
irb(main):037:0> new_array
=> [2, 3, 4]
irb(main):038:0> new_array.map{|e| [e,e]}.flatten
=> [2, 2, 3, 3, 4, 4]
irb(main):039:0> new_array.map{|e| [e,e]}.flatten.unshift(first)
=> [1, 2, 2, 3, 3, 4, 4]
irb(main):040:0> new_array.map{|e| [e,e]}. flatten. unshift(first). push(last)
=> [1, 2, 2, 3, 3, 4, 4, 5]
irb(main):041:0>

kind regards -botp

# Li

Robert Klemme wrote:

···

On 21.11.2006 08:18, William James wrote:
> 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]

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

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

Hi --

···

On Tue, 21 Nov 2006, Daniel N wrote:

On 11/21/06, Daniel N <has.sox@gmail.com> wrote:

Sorry missed a brace on the block. Should be

b = a.inject( ) { |a,e| a << [e,e]}.flatten[1..-2] }

I so much think it's time for flatten to take an argument, specifying
number of levels to flatten. My flattenx extension does this, and it
seems like a natural fit for flatten itself. Otherwise almost all
flatten-based techniques run the risk of over-flattening.

David

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

J. B. Rainsberger wrote:

Of course, if we know the items in the array are in ascending order, we
can /really/ cheat:

b = (a*2).sort[1..-2]

That's as many as I could think of.

Thank you but elements in the array are in random order.

Li

···

--
Posted via http://www.ruby-forum.com/\.

Thank you all for your invalulabe inputs.

Based on what I understand and my personal preference I choose the
following scripts.

Li

···

####
array=[1,2,3,4,5]

array_new=Array.new
array.each {|e| array_new<<[e,e]}

array_new.flatten![1..-2].each{|e| print "#{e}\t" }

puts

##output

ruby sur3.rb

1 2 2 3 3 4 4 5

Exit code: 0

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:

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]

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]

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

···

On 21.11.2006 10:16, William James wrote:

On 21.11.2006 08:18, William James wrote:

Li Chen wrote:

Thank you all for your invalulabe inputs.

Based on what I understand and my personal preference I choose the
following scripts.

Li

####
array=[1,2,3,4,5]

array_new=Array.new
array.each {|e| array_new<<[e,e]}

array_new.flatten![1..-2].each{|e| print "#{e}\t" }

puts

##output

ruby sur3.rb

1 2 2 3 3 4 4 5

Exit code: 0

This is the best I could come up with. It works with any kind of element
including embedded arrays.

array_new = (temp = array[1..-2]).zip(temp).inject(){|n, e|
n.concat(e) }

irb(main):148:0> array=[1,[2,3],4,5,{6,7},"8"]
=> [1, [2, 3], 4, 5, {6=>7}, "8"]
irb(main):149:0> (temp = array[1..-2])
=> [[2, 3], 4, 5, {6=>7}]
irb(main):150:0> (temp = array[1..-2]).zip(temp)
=> [[[2, 3], [2, 3]], [4, 4], [5, 5], [{6=>7}, {6=>7}]]
irb(main):151:0> (temp = array[1..-2]).zip(temp).inject() {|new, elem|
new.concat(elem) }
=> [[2, 3], [2, 3], 4, 4, 5, 5, {6=>7}, {6=>7}]

···

--
Posted via http://www.ruby-forum.com/\.