Array Practice

A

Adam Akhtar

As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

Heres how i did it (im new to both programming and ruby)

def subpack(list)
uniqlist = Array.new
subpacklist = Array.new
list.sort!

uniqlist = list.uniq
uniqlist.each_index do |i|
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)
end
subpacklist
end


WITHOUT GIVING ME YOUR SOLUTION IN FULL, how could i improve this...
i.e. give me some hints, the names of some methods but not the solution
as i want a go myself.
 
S

Siep Korteling

Adam Akhtar wrote:
(...)
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)


I like the index/rindex trick. I have actualy done a similar job, going
through a big logfile to see which users were most active.
I opted for an array of hashes, with the frequency as value.
My result would have been:
[{1=>3},{2=>4},{3=>2},{4=>1}]
Can adapt your code to do the same?
 
R

Rob Biedenharn

As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within
an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

Heres how i did it (im new to both programming and ruby)

def subpack(list)
uniqlist = Array.new
subpacklist = Array.new
list.sort!

uniqlist = list.uniq
uniqlist.each_index do |i|
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)
end
subpacklist
end


WITHOUT GIVING ME YOUR SOLUTION IN FULL, how could i improve this...
i.e. give me some hints, the names of some methods but not the
solution
as i want a go myself.



Think about how you might do it with a pencil...
- write the values out in order "[ 1, 1, 1, 2, 2, 2, 2, 3, 3, 4 ]"
- if the "next" value is different from the last value processed (and
initially there is no last value), then start a new sub-array with
this single value (my pencil would insert a '[' between the '[' and '1')
- ...and if you'd already written a '[', you have to then write "],["
- if the next value is the same, move your pencil (since it goes in
the current sub-array)
- when you run out of values, close the final subarray with ']'

It shouldn't take much to think about how this turns into Ruby
(keeping in mind that Arrays are always finite so you don't really
have to "write" the ']')

-Rob

Rob Biedenharn http://agileconsultingllc.com
(e-mail address removed)
 
A

Adam Akhtar

Well you know what, as i was thinking of a solution to this, hashes
popped into my head. I didnt know how they would be used but soemthing
whired and said you could probably do it with them. I always tend to shy
away from them but seeing as you laid down the challenge ill go away and
try and replicate your way. cheers!

In the meantime keep em coming!
 
S

Siep Korteling

Siep Korteling wrote:
(...)
[{1=>3},{2=>4},{3=>2},{4=>1}]
Can adapt your code to do the same?

Sorry. This should read
{1=>3, 2=>4, 3=>2, 4=>1}
Can you adapt your code to do the same?

Maybe you'd have to read up on hashes before you planned to. I'm
learning the same way as you do. Getting some grip on Fixnum, String,
Array, Hash, File and Date enabled me to write better scripts then I did
with any other scripting language.

Regards,

Siep
 
7

7stud --

Adam said:
As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

Heres how i did it (im new to both programming and ruby)

def subpack(list)
uniqlist = Array.new
subpacklist = Array.new
list.sort!

uniqlist = list.uniq
uniqlist.each_index do |i|
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)
end
subpacklist
end


WITHOUT GIVING ME YOUR SOLUTION IN FULL, how could i improve this...
i.e. give me some hints, the names of some methods but not the solution
as i want a go myself.


Another way would be to iterate over your original array and add each
number to a Hash as you go. A Hash keys will be one of the numbers,
and the corresponding value will be an array containing all of that
particular number.

You can create a new Hash so that when you access a non existent key in
a Hash an empty array will be returned. See the block form of
Hash.new().

Finally, you can create your final array from the hash values using
Hash#values.
 
T

Todd Benson

As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

Heres how i did it (im new to both programming and ruby)

def subpack(list)
uniqlist = Array.new
subpacklist = Array.new
list.sort!

uniqlist = list.uniq
uniqlist.each_index do |i|
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)
end
subpacklist
end


WITHOUT GIVING ME YOUR SOLUTION IN FULL, how could i improve this...
i.e. give me some hints, the names of some methods but not the solution
as i want a go myself.


My solution uses #uniq, #each, #<<, #select, and #==. Oh, and #[]

Todd
 
C

Curt Sampson

[1,2,3,1,2,2,4,3,2,1]
and then grouping them together and putting them in subarrays within an
array like this
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

The Array#assoc method is your friend here.

If you have questions or comments on this, please Cc: me directly as
well as sending to the list. (This should happen automatically if the
list doesn't wipe out my reply-to header.)

cjs
 
C

Clifford Heath

Curt said:
[1,2,3,1,2,2,4,3,2,1]
and then grouping them together and putting them in subarrays within an
array like this
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

The Array#assoc method is your friend here.

Really? Where's the array containing arrays come from?

------------------------------------------------------------ Array#assoc
array.assoc(obj) -> an_array or nil
------------------------------------------------------------------------
Searches through an array whose elements are also arrays comparing
obj with the first element of each contained array using obj.==.
Returns the first contained array that matches (that is, the first
associated array), or nil if no match is found. See also
Array#rassoc.

Clifford Heath.
 
C

Christopher Dicely

Anytime I want to "build up" something from an existing Enumerable
object (Array, etc.) in Ruby, I usually look to inject or collect; the
most elegant of the way I've come up with of doing exactly what you
want uses ==, *, uniq, collect, find_all, and size, and the function
body fits on a single line without semi-colons. (I'm not holding up
that it is a one-liner as a strength, just as a description.)
 
C

Christopher Dicely

Oh, and uses [].

Anytime I want to "build up" something from an existing Enumerable
object (Array, etc.) in Ruby, I usually look to inject or collect; the
most elegant of the way I've come up with of doing exactly what you
want uses ==, *, uniq, collect, find_all, and size, and the function
body fits on a single line without semi-colons. (I'm not holding up
that it is a one-liner as a strength, just as a description.)

As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

Heres how i did it (im new to both programming and ruby)

def subpack(list)
uniqlist = Array.new
subpacklist = Array.new
list.sort!

uniqlist = list.uniq
uniqlist.each_index do |i|
rangeleft = list.index(uniqlist)
rangeright = list.rindex(uniqlist)
subpacklist << list.slice(rangeleft..rangeright)
end
subpacklist
end


WITHOUT GIVING ME YOUR SOLUTION IN FULL, how could i improve this...
i.e. give me some hints, the names of some methods but not the solution
as i want a go myself.
 
R

Rob Biedenharn

Curt said:
[1,2,3,1,2,2,4,3,2,1]
and then grouping them together and putting them in subarrays
within an
array like this
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]
The Array#assoc method is your friend here.

Really? Where's the array containing arrays come from?

------------------------------------------------------------
Array#assoc
array.assoc(obj) -> an_array or nil
------------------------------------------------------------------------
Searches through an array whose elements are also arrays
comparing obj with the first element of each contained array
using obj.==. Returns the first contained array that matches
(that is, the first associated array), or nil if no match is
found. See also Array#rassoc.

Clifford Heath.


Array#assoc searches an existing array of arrays; it doesn't build one.

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ].assoc(2) => [2,2,2,2]
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ].assoc(5) => nil

-Rob

Rob Biedenharn http://agileconsultingllc.com
(e-mail address removed)
 
C

Curt Sampson

...the most elegant of the way I've come up with of doing exactly
what you want uses ==, *, uniq, collect, find_all, and size, and the
function body fits on a single line without semi-colons.

Hm. My function uses: inject, assoc, and, or, <<, [...]. The function
body fits easily on an 80 column line with one semicolon, if I shorten
the variable name "result" to "r".

cjs
 
D

Dave Thomas

Anytime I want to "build up" something from an existing Enumerable
object (Array, etc.) in Ruby, I usually look to inject or collect; the
most elegant of the way I've come up with of doing exactly what you
want uses ==, *, uniq, collect, find_all, and size, and the function
body fits on a single line without semi-colons. (I'm not holding up
that it is a one-liner as a strength, just as a description.)

Ruby 1.9 lets you do it with a few less methods... (I'll give it away
because I'm fairly sure the OP won't be using 1.9). Of course, it only
works on immediate values...

[1,2,3,1,2,2,4,3,2,1].group_by(&:eek:bject_id).values



Cheers


Dave
 
C

Charles Snider

[Note: parts of this message were removed to make it a legal post.]

one line (36 chars) with uniq, map, and select

Curt said:
On 2008-02-07 08:20 +0900 (Thu), Adam Akhtar wrote:
[1,2,3,1,2,2,4,3,2,1]
and then grouping them together and putting them in subarrays
within an
array like this
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]
The Array#assoc method is your friend here.

Really? Where's the array containing arrays come from?

------------------------------------------------------------
Array#assoc
array.assoc(obj) -> an_array or nil
------------------------------------------------------------------------
Searches through an array whose elements are also arrays
comparing obj with the first element of each contained array
using obj.==. Returns the first contained array that matches
(that is, the first associated array), or nil if no match is
found. See also Array#rassoc.

Clifford Heath.


Array#assoc searches an existing array of arrays; it doesn't build one.

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ].assoc(2) => [2,2,2,2]
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ].assoc(5) => nil

-Rob

Rob Biedenharn http://agileconsultingllc.com
(e-mail address removed)
 
B

botp

As some of you may know from previous threads im trying to practice
specific areas of ruby. One simple exercise i set myself was taking a
elements in an array such as

[1,2,3,1,2,2,4,3,2,1]

and then grouping them together and putting them in subarrays within an
array like this

[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]

irb(main):002:0> a=[1,2,3,1,2,2,4,3,2,1]
=> [1, 2, 3, 1, 2, 2, 4, 3, 2, 1]
irb(main):003:0> a.group_by{|x|x}
=> {1=>[1, 1, 1], 2=>[2, 2, 2, 2], 3=>[3, 3], 4=>[4]}
irb(main):004:0> a.group_by{|x|x}.values
=> [[1, 1, 1], [2, 2, 2, 2], [3, 3], [4]]

ruby1.9 though. i'm threading on 1.9 since it is fast, i mean really
fast, even on windows :)
kind regards -botp
 
C

Curt Sampson

one line (36 chars) with uniq, map, and select

Note that, given the output specification, I wonder if it isn't important
that the input objects themselves be preserved in the output array. I did
a test for that:

class AlwaysEqual
def ==(o); true; end
def hash; 0; end
end

def test_group_references
a = AlwaysEqual.new
b = AlwaysEqual.new
r = group([a, b])
assert_equal([[a, b]], r)
assert_same(a, r[0][0])
assert_same(b, r[0][1])
end

cjs
 
A

Adam Akhtar

Rob said:
[ [1,1,1], [2,2,2,2] , [3,3] ,[4] ]
rangeleft = list.index(uniqlist)
as i want a go myself.

Think about how you might do it with a pencil...
- write the values out in order "[ 1, 1, 1, 2, 2, 2, 2, 3, 3, 4 ]"
- if the "next" value is different from the last value processed (and
initially there is no last value), then start a new sub-array with
this single value (my pencil would insert a '[' between the '[' and '1')
- ...and if you'd already written a '[', you have to then write "],["
- if the next value is the same, move your pencil (since it goes in
the current sub-array)
- when you run out of values, close the final subarray with ']'


well heres my way of doing the above:-

def subpackarray passedlist

orderedlist = passedlist.sort
subgrouplist = Array.new
orderedlist.each_index do |i|
if ((i == 0) || (orderedlist != orderedlist[i-1]))
#create a new subgroup array and add the element.
subgrouplist << Array.new
subgrouplist.last.push orderedlist
else
#add element to existing subgroup
subgrouplist.last.push orderedlist
end
end
subgrouplist
end


i think thats the way he was intending it. Ill start figuring out the
others as well. Thanks so much for the posts. I think this makes great
practice asking for hints rather than just reading someone elses code.
 
A

Adam Akhtar

and with hashes

def subpack(passedlist)
hsh = Hash.new
subpacklist = []
#create a hsh of element frequency
passedlist.each do |element|
hsh[element] = hsh[element].to_i + 1
end

hsh.each do |key, value|
subgroup = Array.new
value.times {subgroup.push(key)}
subpacklist << subgroup
end
subpacklist
end
 

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,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top