array question

L

Li Chen

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
 
W

Wilson Bilkovich

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

#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.
 
D

dblack

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) }
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

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

dblack

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.

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 | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

dblack

Hi --

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 | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
L

Li Chen

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
 
W

Wilson Bilkovich

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

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.
 
J

J. B. Rainsberger

Daniel said:
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 :(

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.
 
L

Li Chen

J. B. Rainsberger said:
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
 
W

William James

Li said:
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]
 
R

Robert Klemme

Li said:
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
 
W

William James

Robert said:
Li said:
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
 
R

Robert Klemme

Robert said:
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. :)
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
 
F

Florian Frank

Li said:
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
 
W

William James

Robert said:
Robert said:
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]

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. :)

Ha, ha. Also ugly.
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]

But it has "[1...-1]"! Indexing with literal numbers is so horrid.
 
L

Li Chen

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
 
R

Robert Klemme

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" }

That's pretty inefficient. Why don't you do this?

array.each {|e| array_new << e << e}

Then you don't need to flatten.

robert
 
E

Edwin Fine

Li said:
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}]
 
R

Roseanne Zhang

Edwin said:
Li said:
####
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

I don't know why we need flatten, it is flatten before you do it.

Code:
array_new=[]
array.each {|e| array_new+=[e,e]} #use << will get the same result
array_new = array_new[1..-2]
puts [array_new.join(' ')]
 
L

Louis J Scoras

I love Enumerator so much =)

require 'enumerator'

class Array
def duplicate_internal
to_enum:)each_cons,2).inject([]) do |r, c|
r + c
end
end
end

p [1,2,3,4].duplicate_internal # => [1, 2, 2, 3, 3, 4]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,069
Latest member
SimplyleanKetoReviews

Latest Threads

Top