如何实现 Ruby max_by 到 return 所有具有最大值的元素?
How to implement Ruby max_by to return all elements which have the maximum value?
Ruby max_by 方法查找数组中的最大元素。有时最大元素具有多重性,在这种情况下 max_by 只选择其中一个,看似任意。当我需要所有这些时,我目前使用这种方法来查找数组数组中的最大值:
sorted=ary.sort_by{|a,b| b}.reverse
max_score=sorted.first[1]
t=sorted.take_while{|z| z[1]==max_score}
但是我怎么能用“maxes_by”方法猴子修补数组class,它接受一个块,类似于max_by,returns一个最大值数组?
无需编写 returns 预期输出的新优化方法,您只需组合 max_by
and select
:
maximum = array.max_by { |element| element[1] }
t = array.select { |element| element[1] == maximum[1] }
另一种选择可能是根据相关值(group_by
)对所有元素进行分组,然后只选择具有最大值的列表。
lists = array.group_by { |element| element[1] }
lists[lists.keys.maximum]
值得一提的是,该任务可以通过数组单次传递完成,或者更一般地说,通过任何 class 包含 Enumerable
.[=20 的集合单次传递即可完成=]
module Enumerable
def max_by_all
return each unless block_given?
last_yield = nil
each_with_object([]) do |e,a|
ye = yield(e)
case last_yield.nil? ? -1 : last_yield <=> ye
when -1
a.replace([e])
last_yield = ye
when 0
a << e
end
end
end
end
arr = [2, 4, 3, 4, 1, 2, 5, 3, 5, 1]
arr.max_by_all(&:itself)
#=> [5, 5]
arr = ["style", "assets", "misty", "assist", "corgi", "bossy", "bosses", "chess"]
arr.max_by_all { |s| s.count('s') }
#=> ["assets", "assist", "bosses"]
h = { a: 1, b: 3, c: 2, d: 3, e: 1 }
h.max_by_all(&:last)
#=> [[:b, 3], [:d, 3]]
arr = [1, 2, 3]
arr.max_by_all.map { |n| 2*n }
#=> [2, 4, 6]
在最后一个示例中,max_by_all
没有块,因此 returns 是一个仅枚举 self
元素的枚举器。这种行为可能看起来毫无意义,但我已经提供了它(return each unless block_given?
行)以模仿 Enumerable#max_by 在没有提供块时的行为。
使用猴子补丁
class Array
def maxes_by
maximal = max_by { |x| yield(x) }
select { |x| yield(x) == yield(maximal) }
end
end
- 用法
> ['house', 'car', 'mouse'].maxes_by { |x| x.length }
=> ['house', 'mouse']
但我不建议对 Array
class 进行猴子修补,这种做法很危险,可能会对您的系统造成不良影响。
为了我们好,ruby 语言提供了一个很好的特性来克服这个问题,Refinements,这是在 ruby.[=18= 上进行猴子修补的安全方法]
为简化起见,使用 Refinements 你可以猴子修补 Array
class 并且更改将仅在正在使用的 class 范围内可用细化! :)
您可以在您正在处理的 class 中使用优化,您可以开始了。
使用优化
module MaxesByRefinement
refine Array do
def maxes_by
maximal = max_by { |x| yield(x) }
select { |x| yield(x) == yield(maximal) }
end
end
end
class MyClass
using MaxesByRefinement
def test
a = %w(house car mouse)
a.maxes_by { |x| x.length } # maxes_by is available here!
end
end
- 用法
> MyClass.new.test
=> ['house', 'mouse']
Ruby max_by 方法查找数组中的最大元素。有时最大元素具有多重性,在这种情况下 max_by 只选择其中一个,看似任意。当我需要所有这些时,我目前使用这种方法来查找数组数组中的最大值:
sorted=ary.sort_by{|a,b| b}.reverse
max_score=sorted.first[1]
t=sorted.take_while{|z| z[1]==max_score}
但是我怎么能用“maxes_by”方法猴子修补数组class,它接受一个块,类似于max_by,returns一个最大值数组?
无需编写 returns 预期输出的新优化方法,您只需组合 max_by
and select
:
maximum = array.max_by { |element| element[1] }
t = array.select { |element| element[1] == maximum[1] }
另一种选择可能是根据相关值(group_by
)对所有元素进行分组,然后只选择具有最大值的列表。
lists = array.group_by { |element| element[1] }
lists[lists.keys.maximum]
值得一提的是,该任务可以通过数组单次传递完成,或者更一般地说,通过任何 class 包含 Enumerable
.[=20 的集合单次传递即可完成=]
module Enumerable
def max_by_all
return each unless block_given?
last_yield = nil
each_with_object([]) do |e,a|
ye = yield(e)
case last_yield.nil? ? -1 : last_yield <=> ye
when -1
a.replace([e])
last_yield = ye
when 0
a << e
end
end
end
end
arr = [2, 4, 3, 4, 1, 2, 5, 3, 5, 1]
arr.max_by_all(&:itself)
#=> [5, 5]
arr = ["style", "assets", "misty", "assist", "corgi", "bossy", "bosses", "chess"]
arr.max_by_all { |s| s.count('s') }
#=> ["assets", "assist", "bosses"]
h = { a: 1, b: 3, c: 2, d: 3, e: 1 }
h.max_by_all(&:last)
#=> [[:b, 3], [:d, 3]]
arr = [1, 2, 3]
arr.max_by_all.map { |n| 2*n }
#=> [2, 4, 6]
在最后一个示例中,max_by_all
没有块,因此 returns 是一个仅枚举 self
元素的枚举器。这种行为可能看起来毫无意义,但我已经提供了它(return each unless block_given?
行)以模仿 Enumerable#max_by 在没有提供块时的行为。
使用猴子补丁
class Array
def maxes_by
maximal = max_by { |x| yield(x) }
select { |x| yield(x) == yield(maximal) }
end
end
- 用法
> ['house', 'car', 'mouse'].maxes_by { |x| x.length }
=> ['house', 'mouse']
但我不建议对 Array
class 进行猴子修补,这种做法很危险,可能会对您的系统造成不良影响。
为了我们好,ruby 语言提供了一个很好的特性来克服这个问题,Refinements,这是在 ruby.[=18= 上进行猴子修补的安全方法]
为简化起见,使用 Refinements 你可以猴子修补 Array
class 并且更改将仅在正在使用的 class 范围内可用细化! :)
您可以在您正在处理的 class 中使用优化,您可以开始了。
使用优化
module MaxesByRefinement
refine Array do
def maxes_by
maximal = max_by { |x| yield(x) }
select { |x| yield(x) == yield(maximal) }
end
end
end
class MyClass
using MaxesByRefinement
def test
a = %w(house car mouse)
a.maxes_by { |x| x.length } # maxes_by is available here!
end
end
- 用法
> MyClass.new.test
=> ['house', 'mouse']