[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Noob: The ruby way to multiple Array by multiple?

Eric Luo

3/28/2006 10:06:00 AM

I want to make a Array multipled by another Array, and the following semantic.
For example:
[1, 2, 3] * [4, 5]
then I will want [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]] returned.

I have the following code snippet to implement this function:

class Array
alias_method :orig_multiple, :*
def *(arg)
case arg
when Array
if arg.empty?
self
else
inject([]) do |product, item|
product.concat(arg.collect do |i|
case item
when Array
item.clone << i
else
[item, i]
end
end)
end
end
else
orig_multiple(arg)
end
end
end

It works but seems ugly.

Could anyone please to give me a clue to make it beauty and rubish!

Thx in advance.
Eric
4 Answers

Robert Klemme

3/28/2006 10:19:00 AM

0

Eric Luo wrote:
> I want to make a Array multipled by another Array, and the following semantic.
> For example:
> [1, 2, 3] * [4, 5]
> then I will want [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]] returned.
>
> I have the following code snippet to implement this function:
>
> class Array
> alias_method :orig_multiple, :*
> def *(arg)
> case arg
> when Array
> if arg.empty?
> self
> else
> inject([]) do |product, item|
> product.concat(arg.collect do |i|
> case item
> when Array
> item.clone << i
> else
> [item, i]
> end
> end)
> end
> end
> else
> orig_multiple(arg)
> end
> end
> end
>
> It works but seems ugly.
>
> Could anyone please to give me a clue to make it beauty and rubish!
>
> Thx in advance.
> Eric

res = []
a1.each {|e1| a2.each {|e2| res << [e1,e2]}}

Or, if you prefer inject

a1.inject([]) {|arr,e1| a2.each {|e2| arr << [e1,e2]}; arr }

Kind regards

robert

Ryan Davis

3/28/2006 10:52:00 AM

0


On Mar 28, 2006, at 2:08 AM, Eric Luo wrote:

> I want to make a Array multipled by another Array, and the
> following semantic.
> For example:
> [1, 2, 3] * [4, 5]
> then I will want [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
> returned.

a = [1, 2, 3]
b = [4, 5]

(a * b.size).zip(b * a.size).sort
# => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]

# or w/o sort:
a.zip(a).flatten.zip(b * a.size)
# => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]

# the latter only works as-is because b.size == 2 (a.zip(a).flatten
~= a * 2).
# If b.size were 3, you'd add b.size-1 a's to the first zip arg list:

b << 6
a.zip(a, a).flatten.zip(b * a.size)
# => [[1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5],
[3, 6]]

# if order doesn't actually matter, the first solution is the cleanest:

class Array
def x(b)
a = self
(a * b.size).zip(b * a.size)
end
end

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

--
ryand-ruby@zenspider.com
http://www.zenspider.com/... - Seattle.rb
http://blog.zens...




Pit Capitain

3/28/2006 12:31:00 PM

0

Ryan Davis schrieb:
> a = [1, 2, 3]
> b = [4, 5]
>
> (a * b.size).zip(b * a.size).sort
> # => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
>
> ...
>
> class Array
> def x(b)
> a = self
> (a * b.size).zip(b * a.size)
> end
> end
>
> a.x b
> => [[1, 4], [2, 5], [3, 6], [1, 4], [2, 5], [3, 6], [1, 4], [2, 5], [3,
> 6]]

Ryan, this works only if a.size and b.size are relatively prime, as in
your first example. The second example shows the error. If you use sort
in a different place it should work, though:

(a * b.size).sort.zip(b * a.size)

Regards,
Pit


Eric Luo

3/29/2006 3:05:00 AM

0

Ryan> class Array
Ryan> def x(b)
Ryan> a = self
Ryan> (a * b.size).zip(b * a.size)
Ryan> end
Ryan> end

Ryan> a.x b
Ryan> => [[1, 4], [2, 5], [3, 6], [1, 4], [2, 5], [3, 6], [1, 4], [2, 5],
Ryan> [3, 6]]

Thanks for your hint, It seems so simple and pretty.