convert array to array-of-arrays?

P

Phlip

Rubies:

Given [1, 2, 3, 4], what's the most Rubiesque way to get [[1, 2], [3, 4]]?

I had figured a variation on Array#transpose would be available, but I can't
find one!
 
P

Phlip

Chris said:
Given [1, 2, 3, 4], what's the most Rubiesque way to get [[1, 2], [3, 4]]?
have a look at enum.partition (http://ruby-doc.org/core/classes/
Enumerable.html#M003161)

I can't partition by value, so the closest conceptual match would be something like:

assert do
[1, 2, 3, 7].partition_with_index{|p,i| i.odd? }.transpose ==
[[1, 2], [3, 7]]
end

And that's a heckuva lot of typing, even if partition_with_index existed!
 
R

Reacher

Chris said:
Given [1, 2, 3, 4], what's the most Rubiesque way to get [[1, 2], [3, 4]]?
have a look at enum.partition (http://ruby-doc.org/core/classes/
Enumerable.html#M003161)

I can't partition by value, so the closest conceptual match would be something like:

    assert do
       [1, 2, 3, 7].partition_with_index{|p,i| i.odd? }.transpose ==
            [[1, 2], [3, 7]]
    end

And that's a heckuva lot of typing, even if partition_with_index existed!

Roll your own?

class Array
def regroup(count)
# do some Ruby awesomeness*
end
end
a = [1, 2, 3, 4] [1, 2, 3, 4]
a.regroup(2)
[[1, 2], [3, 4]]

* - exercise left up to the reader
 
R

Robert Klemme

2008/2/4 said:
Given [1, 2, 3, 4], what's the most Rubiesque way to get [[1, 2], [3, 4]]?

I had figured a variation on Array#transpose would be available, but I can't
find one!

have a look at enum.partition (http://ruby-doc.org/core/classes/
Enumerable.html#M003161)

Not sure what the OP wants, but AFAIK #partition only ever returns two
partitions. If the task is to combine consecutive elements
#each_slice works well:

$ irb -r enumerator
irb(main):001:0> [1, 2, 3, 4].to_enum:)each_slice, 2).to_a
=> [[1, 2], [3, 4]]
irb(main):002:0>

Kind regards

robert
 
C

Chris Hulan

Chris said:
Given [1, 2, 3, 4], what's the most Rubiesque way to get [[1, 2], [3, 4]]?
have a look at enum.partition (http://ruby-doc.org/core/classes/
Enumerable.html#M003161)

I can't partition by value, so the closest conceptual match would be something like:

assert do
[1, 2, 3, 7].partition_with_index{|p,i| i.odd? }.transpose ==
[[1, 2], [3, 7]]
end

And that's a heckuva lot of typing, even if partition_with_index existed!

Have a look at Facets.Enumerable.group_by (http://facets.rubyforge.org/
quick/rdoc/core/classes/Enumerable.html#M000423)
Lots of other neat stuff there...

Cheers
 
P

Phlip

Robert said:
irb(main):001:0> [1, 2, 3, 4].to_enum:)each_slice, 2).to_a

Thanks! Now, for those of us mired in the doldrums of Ruby 1.8.x, how to write
to_enum in Ruby? I found each_slice, and I know C and ruby.h, but my Ruby
internals are rusty...
 
P

Phlip

The winner is ActiveSupport's Array#in_groups_of (calling each_slice).

Thanks y'all!

But it only won for one reason - I need the array-of-twos so I can then
immediately call .each on it. in_groups_of already requires a block (and does
not return the twizzled array!), so I can just use it without the each. So I
would have called it each_group, but that didn't seem to catch on...

Here's why I need it. Ruby's opcodes express Hashes as strictly even-lengthed
arrays, going [key1, value1, key2, value2, etc]. So I just needed to iterate
those things in pairs, without excessive moduli to detect if the current item is
a key or a value.
 
C

Chris Hulan

Robert said:
irb(main):001:0> [1, 2, 3, 4].to_enum:)each_slice, 2).to_a

Thanks! Now, for those of us mired in the doldrums of Ruby 1.8.x, how to write
to_enum in Ruby? I found each_slice, and I know C and ruby.h, but my Ruby
internals are rusty...

Ruby-docs.org indicates Object.to_enum exists in latest 1.8.6, can you
upgrade?
 
P

Phlip

Chris said:
Ruby-docs.org indicates Object.to_enum exists in latest 1.8.6, can you
upgrade?

1.8.6 p111!

But here's the before and after on that refactor:

- array.each_with_index do |n, index|
- expression << _send(n)
- if (index % 2) == 0
- expression << ' => '
- elsif n != array.last
- expression << ', '
- end
- end

+ array.in_groups_of 2 do |key, value|
+ expression << _send(key) + ' => ' + _send(value)
+ expression << ', ' if value != array.last
+ end

Getting tight, huh? C-; Only one if to go...
 
R

Robert Klemme

Robert said:
irb(main):001:0> [1, 2, 3, 4].to_enum:)each_slice, 2).to_a

Thanks! Now, for those of us mired in the doldrums of Ruby 1.8.x, how to
write to_enum in Ruby? I found each_slice, and I know C and ruby.h, but
my Ruby internals are rusty...

AFAIK it is in *all* Ruby 1.8.* versions. You just need an extra
"require" (see my first posting in this thread).

Cheers

robert
 
R

Robert Klemme

Robert said:
irb(main):001:0> [1, 2, 3, 4].to_enum:)each_slice, 2).to_a

Thanks! Now, for those of us mired in the doldrums of Ruby 1.8.x, how
to write to_enum in Ruby? I found each_slice, and I know C and ruby.h,
but my Ruby internals are rusty...

PS: In case you wondered: it's pretty easy:

$ irb
irb(main):001:0> EnumProxy = Struct.new :eek:bj, :args do
irb(main):002:1* include Enumerable
irb(main):003:1> def each(&b)
irb(main):004:2> obj.send(*args,&b)
irb(main):005:2> self
irb(main):006:2> end
irb(main):007:1> end
=> EnumProxy
irb(main):008:0> class Object
irb(main):009:1> def to_enum(*a)
irb(main):010:2> EnumProxy.new self, a
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> %w{foo bar}.to_enum:)each_with_index).each {|*a| p a}
["foo", 0]
["bar", 1]
=> #<struct EnumProxy obj=["foo", "bar"], args=[:each_with_index]>
irb(main):014:0> %w{foo bar}.to_enum:)each_with_index).find {|a,b| b==1}
=> ["bar", 1]

Kind regards

robert
 
R

Robert Klemme

The winner is ActiveSupport's Array#in_groups_of (calling each_slice).

Thanks y'all!

But it only won for one reason - I need the array-of-twos so I can then
immediately call .each on it. in_groups_of already requires a block (and
does not return the twizzled array!), so I can just use it without the
each. So I would have called it each_group, but that didn't seem to
catch on...

Here's why I need it. Ruby's opcodes express Hashes as strictly
even-lengthed arrays, going [key1, value1, key2, value2, etc]. So I just
needed to iterate those things in pairs, without excessive moduli to
detect if the current item is a key or a value.

"Excessive moduli"?

irb(main):003:0> %w{foo bar}.each_with_index {|e,i| puts "key #{e}" if i
% 2 == 0}
key foo
=> ["foo", "bar"]
irb(main):004:0> %w{foo bar}.each_with_index {|e,i| puts "key #{e}" if i
& 1 == 0}
key foo
=> ["foo", "bar"]

Cheers

robert
 
P

Phlip

Reacher said:
Roll your own?

class Array
def regroup(count)

If the result's going into a published library, I must survey the prior art.
That improves the odds I remain compatible when the community's best version of
this feature rolls up into the standard Array class.
 

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

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top