Hi,
I'm looking for an elegant way to do the following:
Given an sorted array of (X,Y) pairs where Y is strictly
increasing, i.e., no repeated Ys.
Compact pairs with repeated Xs, keeping the pair with
the highest Y value.
E.g.,
require 'test/unit'
class TestConsolidation < Test::Unit::TestCase
def test_should_remove_repeated_Xs_but_save_one_with_highest_Y
initial = [ [ 1, 12 ], [ 3, 15 ], [ 3, 17 ], [ 3, 22 ], [ 7, 45 ] ]
desired = [ [ 1, 12 ], [ 3, 22 ], [ 7, 45 ] ]
assert_equal desired, initial.consolidate
end
end
class Array
def consolidate
# Too embarrassed to show current hack.
end
end
My least surprise inclination had me researching #uniq and #compact
to see if they took a block like #sort .
Thanks,
···
--
Bil Kleb
http://fun3d.larc.nasa.gov
Bil, this makes the test pass:
class Array
def consolidate
Hash[*flatten].sort
end
end
Regards,
Pit
···
2008/1/7, Bil Kleb <Bil.Kleb@nasa.gov>:
I'm looking for an elegant way to do the following:
(...)
This is easy with #inject:
ar.inject( ) do |res, (x,y)|
if res.empty? || res.last[0] != x
res << [x,y]
else
res.last[1] = y
end
res
end
Cheers
robert
···
2008/1/7, Bil Kleb <Bil.Kleb@nasa.gov>:
Hi,
I'm looking for an elegant way to do the following:
Given an sorted array of (X,Y) pairs where Y is strictly
increasing, i.e., no repeated Ys.
Compact pairs with repeated Xs, keeping the pair with
the highest Y value.
E.g.,
require 'test/unit'
class TestConsolidation < Test::Unit::TestCase
def test_should_remove_repeated_Xs_but_save_one_with_highest_Y
initial = [ [ 1, 12 ], [ 3, 15 ], [ 3, 17 ], [ 3, 22 ], [ 7, 45 ] ]
desired = [ [ 1, 12 ], [ 3, 22 ], [ 7, 45 ] ]
assert_equal desired, initial.consolidate
end
end
class Array
def consolidate
# Too embarrassed to show current hack.
end
end
My least surprise inclination had me researching #uniq and #compact
to see if they took a block like #sort .
--
use.inject do |as, often| as.you_can - without end
Pit Capitain wrote:
I'm looking for an elegant way to do the following:
(...)
Bil, this makes the test pass:
class Array
def consolidate
Hash[*flatten].sort
end
end
That certainly is elegant!
Maybe Bil wanted to preserve the monotonicity?
class Array
def consolidate
Hash[*flatten].sort_by {|x,y| y}
end
end
p [ [5,1] , [3,2] ].consolidate # ==> [[5, 1], [3, 2]]
···
2008/1/7, Bil Kleb <Bil.Kleb@nasa.gov>:
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
Bil
(Bil)
12 January 2008 16:15
5
Hey, thanks everyone for the help!
I would have replied sooner, but my USENET feed dropped your replies
and I only now thought to look at groups.google.com.
Thanks again,
···
On Jan 7, 10:45 am, Robert Klemme <shortcut...@googlemail.com> wrote:
This is easy with #inject:
--
http://twitter.com/bil_kleb
A more general solution:
require 'set'
class Array
def uniq(&blk)
blk ||= lambda {|x| x}
already_seen = Set.new
uniq_array =
self.each_with_index do |value, i|
x = blk.call(value)
unless already_seen.include? x
already_seen << x
uniq_array << value
end
end
uniq_array
end
end
and
class Array
def consolidate
reverse.uniq {|a| a.first}.reverse
end
end
Of course, the value that you keep for uniq is kinda arbitrary.
Dan
- Hide quoted text -
···
On 1/7/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
Pit Capitain wrote:
> 2008/1/7, Bil Kleb <Bil.Kleb@nasa.gov>:
>> I'm looking for an elegant way to do the following:
>> (...)
>
> Bil, this makes the test pass:
>
> class Array
> def consolidate
> Hash[*flatten].sort
> end
> end
That certainly is elegant!
Maybe Bil wanted to preserve the monotonicity?
class Array
def consolidate
Hash[*flatten].sort_by {|x,y| y}
end
end
p [ [5,1] , [3,2] ].consolidate # ==> [[5, 1], [3, 2]]
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407