[Q] how to unflatten a flat-array

  • Thread starter SHIGETOMI, Takuhiko
  • Start date
S

SHIGETOMI, Takuhiko

dear guys,

i am seeking a smart way to do ...

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

especialy, the way hopefully will work safety when the source array's
size is odd or zero.

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
H

Hal Fulton

dear guys,

i am seeking a smart way to do ...

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

especialy, the way hopefully will work safety when the source array's
size is odd or zero.

I have used something like:

arr = array.dup
result = []
while ! arr.empty?
result << arr.slice!(0..1)
end

Would that work for you?


Hal
 
S

SHIGETOMI, Takuhiko

greetings, Hal. gratitude to you.
arr = array.dup
result = []
while ! arr.empty?
result << arr.slice!(0..1)
end

looks like nice to me.
please let me exec it and repot the result to you later.
(sorry, i am now screwed up in my business.)

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
D

David A. Black

Hi --

dear guys,

i am seeking a smart way to do ...

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

especialy, the way hopefully will work safety when the source array's
size is odd or zero.

I've got a method from long ago that might fit:

class Array # or do it as a module, or whatever
def in_slices_of(n)
res = []
0.step(size - 1, n) do |i|
s = slice(i...i + n)
yield s if block_given?
res.push s
end
res
end
end

[1,2,3,4,5,6].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6]]
[1,2,3,4,5,6].in_slices_of(3) # => [[1, 2, 3], [4, 5, 6]]

It handles odd numbers by putting whatever's left over in its own
array:

[1,2,3,4,5,6,7].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6], [7]]

(and note that it yields each slice too).

In 1.9 you can do:

irb(main):015:0> [1,2,3,4,5,6].enum_slice(2).map {|x| x }
=> [[1, 2], [3, 4], [5, 6]]

which handles odd numbers the same way. (I can't seem to get it to
return the desired result without doing the map operation.)


David
 
S

SHIGETOMI, Takuhiko

greetings, David. how nice it is!
I've got a method from long ago that might fit:

class Array # or do it as a module, or whatever
def in_slices_of(n)
res = []
0.step(size - 1, n) do |i|
s = slice(i...i + n)
yield s if block_given?
res.push s
end
res
end
end

[1,2,3,4,5,6].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6]]
[1,2,3,4,5,6].in_slices_of(3) # => [[1, 2, 3], [4, 5, 6]]

It handles odd numbers by putting whatever's left over in its own
array:

[1,2,3,4,5,6,7].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6], [7]]

quick question. (sorry, i am still screwed up.)
will the yieldee ( = the block ) 's 2nd parameter be nil at the end of
the case of odd number as above ?

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
D

David A. Black

Hi --

greetings, David. how nice it is!
I've got a method from long ago that might fit:

class Array # or do it as a module, or whatever
def in_slices_of(n)
res = []
0.step(size - 1, n) do |i|
s = slice(i...i + n)
yield s if block_given?
res.push s
end
res
end
end

[1,2,3,4,5,6].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6]]
[1,2,3,4,5,6].in_slices_of(3) # => [[1, 2, 3], [4, 5, 6]]

It handles odd numbers by putting whatever's left over in its own
array:

[1,2,3,4,5,6,7].in_slices_of(2) # => [[1, 2], [3, 4], [5, 6], [7]]

quick question. (sorry, i am still screwed up.)
will the yieldee ( = the block ) 's 2nd parameter be nil at the end of
the case of odd number as above ?

Yes:

[1,2,3,4,5,6,7].in_slices_of(2).map {|x,y| [x,y]}
=> [[1, 2], [3, 4], [5, 6], [7, nil]]

I don't think there's much choice. (You could of course just catch
each inner array in one variable.)


David
 
J

James Edward Gray II

dear guys,

i am seeking a smart way to do ...

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

especialy, the way hopefully will work safety when the source array's
size is odd or zero.

Pretty hackish but:

irb(main):001:0> arr = [ 1, 2, 3, 4, 5, 6]
=> [1, 2, 3, 4, 5, 6]
irb(main):011:0> arr << nil unless arr.size % 2 == 0
=> nil
irb(main):012:0> Hash[*arr].to_a.sort
=> [[1, 2], [3, 4], [5, 6]]

I was just playing around. I like David's in_slices() method much
better.

James Edward Gray II
 
S

SHIGETOMI, Takuhiko

greeting James. what an intriguing way!

irb(main):001:0> arr = [ 1, 2, 3, 4, 5, 6]
=> [1, 2, 3, 4, 5, 6]
irb(main):011:0> arr << nil unless arr.size % 2 == 0
=> nil
irb(main):012:0> Hash[*arr].to_a.sort
=> [[1, 2], [3, 4], [5, 6]]

for me, as a beginner of ruby,
this is a fascinating black magic.
i will study hard to let it be white. :)

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
S

SHIGETOMI, Takuhiko

greetings, Gene. i have felt that yours is quite a ruby-ish way.
require 'enumerator'
accum=[]
(1..10).each_slice(3) { |sl| accum << sl}
p accum

let me put it into my treasure box.
this is quite useful at the case of that the enumeratee is surely
innocent.

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
R

Robert Klemme

2005/8/29 said:
dear guys,
=20
i am seeking a smart way to do ...
=20
[ 1, 2, 3, 4, 5, 6, ... ] =3D> [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], ... ]
=20
especialy, the way hopefully will work safety when the source array's
size is odd or zero.

This is a pretty much straightforward implementation:
res=3D[]; 0.step(a.length - 1,2) {|i| res << [a,a[i+1]]}; res

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

Kind regards

robert
 
W

William James

dear guys,

i am seeking a smart way to do ...

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

especialy, the way hopefully will work safety when the source array's
size is odd or zero.

ary = [1,2,3,4,5,6,7,8]
f=nil
t=ary.partition{f=!f}
p t[0].zip(t[1])
 
S

SHIGETOMI, Takuhiko

greetings, William. i'm sorry, your way is beyond my light-weight brain.
ary = [1,2,3,4,5,6,7,8]
f=nil
t=ary.partition{f=!f}
p t[0].zip(t[1])

but it works...

$ irb
irb(main):001:0> ary = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):002:0> f=nil
=> nil
irb(main):003:0> t=ary.partition{f=!f}
=> [[1, 3, 5, 7], [2, 4, 6, 8]]
irb(main):004:0> p t[0].zip(t[1])
[[1, 2], [3, 4], [5, 6], [7, 8]]
=> nil

i'd like you use a terrestrial language, or beam me your universal
translator. :)

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
S

SHIGETOMI, Takuhiko

greetings, Robert. thank you, it does make sense to me.
res=[]; 0.step(a.length - 1,2) {|i| res << [a,a[i+1]]}; res

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


i know that an yieldee is 100% passive to its yielder, but i often feel
desire to let it fetch to the next/previous yielded object from inside
the yieldee.

don't you know any cool way to do this in ruby?

--
<name species-designation="5618" default-lang="ja_JP">SHIGETOMI,Takuhiko</name>
<contact medium="email">[email protected]</contact>
<location federational-alias="/galaxy/alpha-quadrant/sector-001/earth/">
/void/3d/universe/milkyway-galaxy/orion's-arm/sol-solar-system/3rd-planet/fareast/jp/tky/
</location>
<hail>resistance is futile.</hail>
 
R

Robert Klemme

2005/8/29 said:
greetings, Robert. thank you, it does make sense to me.
=20
res=3D[]; 0.step(a.length - 1,2) {|i| res << [a,a[i+1]]}; res

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

=20
i know that an yieldee is 100% passive to its yielder, but i often feel
desire to let it fetch to the next/previous yielded object from inside
the yieldee.
=20
don't you know any cool way to do this in ruby?


No, not generally. With arrays you can use #each_with_index and in
the general case of Enumerable you can use inject to access the last
element, along the lines

enum.inject {|last, current| .... ; current}

Kind regards

robert
 
R

Robert Klemme

2005/8/29 said:
greetings, William. i'm sorry, your way is beyond my light-weight brain.

Although I'm not the author I can jump in with an explanation.
ary =3D [1,2,3,4,5,6,7,8]
f=3Dnil
t=3Dary.partition{f=3D!f}
p t[0].zip(t[1])
=20
but it works...

#partition puts contents of an Enumerable into two arrays depending on
the boolean result of a block. For example:
=3D> [[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]]

The code above just toggles a flag (f) on each evaluation of the block
thus putting elements into the first and second array returned
interchangingly.

Array#zip basically iterates two array in lock step. So the first
partition contains x elements and the second partition contains y
elements and #zip creates pairs [x,y] from them.

Although I like this solution because of its cuteness and shortness,
it has the disadvantage of creating two intermediate arrays. That
might or might not be a problem in your case - depending on the array
sizes involved. HTH

Kind regards

robert
 
D

Daniel Brockman

SHIGETOMI said:
i know that an yieldee is 100% passive to its yielder, but
i often feel desire to let it fetch to the next/previous
yielded object from inside the yieldee.

don't you know any cool way to do this in ruby?

You can't easily go backwards, but skipping to the next is
as easy as saying `next'.
 
L

Linus Sellberg

[ 1, 2, 3, 4, 5, 6, ... ] =3D> [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], ... ]

TIMTOWTDI:

def slicer arr, n
arr =3D arr.dup
arr.each_index {|i| arr[i...(i + n)] =3D [arr[i...(i + n)]] }
end

x =3D [1,2,3,4,5,6,7]

slicer x,3
=3D> [[1, 2, 3], [4, 5, 6], [7]]
 
S

SHIGETOMI, Takuhiko

greetings, Daniel. true. 'next' works.
You can't easily go backwards, but skipping to the next is
as easy as saying `next'.

on the other hand, and as your reference 'cannot easyily go backwards',
'next' forgets current object unless any variable on outside of the
yieldee block.

how about writing a special yielder like as below ..

any-enumerable-object.sliding_each do |prev,this,next|
...
end

- could be really useful?
- any other good name?

/void/3d/universe/milky-way-galaxy/orion-arm/sol-solar-system/3rd-planet/fareast/jp/tky/shigetomi.takuhiko.5618
 
D

David A. Black

Hi --

greetings, Daniel. true. 'next' works.


on the other hand, and as your reference 'cannot easyily go backwards',
'next' forgets current object unless any variable on outside of the
yieldee block.

how about writing a special yielder like as below ..

any-enumerable-object.sliding_each do |prev,this,next|
...
end

- could be really useful?
- any other good name?

This might help you on this:

irb(main):003:0> require 'enumerator'
=> true
irb(main):004:0> [1,2,3,4,5,6].each_cons(2) {|x| p x }
[1, 2]
[2, 3]
[3, 4]
[4, 5]
[5, 6]
=> nil
irb(main):005:0> [1,2,3,4,5,6].each_cons(3) {|x| p x }
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]


David
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top