[#106355] [Ruby master Bug#18373] RBS build failure: '/include/x86_64-linux/ruby/config.h', needed by 'constants.o'. — "vo.x (Vit Ondruch)" <noreply@...>
Issue #18373 has been reported by vo.x (Vit Ondruch).
28 messages
2021/12/01
[ruby-core:106469] [Ruby master Feature#18181] Introduce Enumerable#min_with_value, max_with_value, and minmax_with_value
From:
"cvss (Kirill Vechera)" <noreply@...>
Date:
2021-12-03 15:40:52 UTC
List:
ruby-core #106469
Issue #18181 has been updated by cvss (Kirill Vechera).
There's also a frequent similar problem with `#find` when you need to find the first matched value instead of entry. But since it involves two semantically different code parts, it a bit more complex and cannot be implemented nicely with the same approach:
```ruby
%w(abcde fg hijk).find_with_value { |e| (size = e.size).even? && size } # => ['fg', 2]
```
But if we could create a lazy mapping enumerator providing a pair `[entry, value]`, than we can unroll it in the second chain just as much as we need and without a second value computation:
```ruby
%w(abcde fg hijk).lazy_map_with(&:size).find{_2.even?} # => ['fg', 2]
```
And back to `#min_with_value` it could be written as:
```ruby
%w(abcde fg hijk).lazy_map_with(&:size).min_by(&:last) # => ['fg', 2]
```
We can add some shorthand methods specific to this enumerator like these:
```ruby
lm = %w(abcde fg hijk).lazy_map_with(&:size)
lm.min_by_value # => ['fg', 2]
lm.min_value # => 2
lm.find_by_value(&:even?) # => ['fg', 2]
lm.find_value(&:even?) # => 2
```
----------------------------------------
Feature #18181: Introduce Enumerable#min_with_value, max_with_value, and minmax_with_value
https://bugs.ruby-lang.org/issues/18181#change-95126
* Author: kyanagi (Kouhei Yanagita)
* Status: Open
* Priority: Normal
----------------------------------------
PR is https://github.com/ruby/ruby/pull/4874
I propose `Enumerable#min_with_value`, `max_with_value` and `minmax_with_value`.
These methods work like this:
``` ruby
%w(abcde fg hijk).min_with_value { |e| e.size } # => ['fg', 2]
%w(abcde fg hijk).max_with_value { |e| e.size } # => ['abcde', 5]
%w(abcde fg hijk).minmax_with_value { |e| e.size } # => [['fg', 2], ['abcde', 5]]
```
Corresponding to `#min(n)`, an integer argument can be passed to `#min_with_value` or `#max_with_value`.
``` ruby
%w(abcde fg hijk).min_with_value(2) { |e| e.size } # => [['fg', 2], ['hijk', 4]]
%w(abcde fg hijk).max_with_value(2) { |e| e.size } # => [['abcde', 5], ['hijk', 4]]
```
## Motivation
When I use `Enumerable#min_by`, I sometimes want to get not only the minimum element
but also the value from the given block.
(e.g.: There are many points. Find the nearest point and get distance to it.)
``` ruby
elem = enum.min_by { |e| foo(e) }
value = foo(elem)
```
This works, but I'd like to avoid writing foo() twice. (Consider a more complex case.)
This can be written without repeated foo() like belows, but it is slightly complicated and needs extra arrays.
``` ruby
value, elem = enum.map { |e| [foo(e), e] }.min_by(&:first)
```
If the size of enum is enormous, it is hard to use intermediate arrays.
`Enumerable#min_with_value` solves this problem.
I think `min_with_value` is the best name I could think of, but any suggestions for better names would be appreciated.
## Benchmark
https://bugs.ruby-lang.org/issues/18181#note-2
## Example
Solving a traveling salesman problem in nearest neighbor algorithm.
``` ruby
require 'set'
Point = Struct.new(:x, :y)
points = Set.new([Point.new(1, 1), Point.new(2, 4), Point.new(3, 3), Point.new(2, 2), Point.new(0, 1)])
total = 0
current = points.first
points.delete(current)
path = [current]
until points.empty?
current, distance = points.min_with_value do |point|
Math.hypot(current.x - point.x, current.y - point.y)
end
total += distance
points.delete(current)
path << current
end
p path
p total
```
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>