Ruby 查找与给定条件匹配的元素的索引
给定一个数组,如何找到与给定条件匹配的元素的所有索引 例如,如果我有:Ruby 查找与给定条件匹配的元素的索引,ruby,arrays,Ruby,Arrays,给定一个数组,如何找到与给定条件匹配的元素的所有索引 例如,如果我有: arr = ['x', 'o', 'x', '.', '.', 'o', 'x'] 要查找项目为x的所有索引,我可以执行以下操作: arr.each_with_index.map { |a, i| a == 'x' ? i : nil }.compact # => [0, 2, 6] 或 有没有更好的方法来实现这一点?另一种方法: arr.size.times.select {|i| arr[i] == 'x'
arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
要查找项目为x
的所有索引,我可以执行以下操作:
arr.each_with_index.map { |a, i| a == 'x' ? i : nil }.compact # => [0, 2, 6]
或
有没有更好的方法来实现这一点?另一种方法:
arr.size.times.select {|i| arr[i] == 'x'} # => [0, 2, 6]
编辑:
不确定是否需要,但它们在这里
基准:
arr = 10000000.times.map{rand(1000)};
Benchmark.measure{arr.each_with_index.map { |a, i| a == 50 ? i : nil }.compact}
2.090000 0.120000 2.210000 ( 2.205431)
Benchmark.measure{(0..arr.size-1).select { |i| arr[i] == 50 }}
1.600000 0.000000 1.600000 ( 1.604543)
Benchmark.measure{arr.map.with_index {|a, i| a == 50 ? i : nil}.compact}
1.810000 0.020000 1.830000 ( 1.829151)
Benchmark.measure{arr.each_index.select{|i| arr[i] == 50}}
1.590000 0.000000 1.590000 ( 1.584074)
Benchmark.measure{arr.size.times.select {|i| arr[i] == 50}}
1.570000 0.000000 1.570000 ( 1.574474)
使用_index.map行比您的
每个_稍有改进
arr.map.with_index {|a, i| a == 'x' ? i : nil}.compact # => [0, 2, 6]
Ruby 1.9:
arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
p arr.each_index.select{|i| arr[i] == 'x'} # =>[0, 2, 6]
此方法稍长,但速度加倍
class Array
def find_each_index find
found, index, q = -1, -1, []
while found
found = self[index+1..-1].index(find)
if found
index = index + found + 1
q << index
end
end
q
end
end
arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
p arr.find_each_index 'x'
# [0, 2, 6]
不确定你是否认为这是一个改进,但是使用(<代码>地图<代码> +>代码>紧凑< <代码> >作为一个过滤器对我来说感觉很笨拙。我会使用
选择
,因为这就是它的用途,然后抓住我关心的结果部分:
arr.each_with_index.select { |a,i| a == 'x' }.map &:last
我定义了Array#index_all
,其行为类似于Array#index
,但返回所有匹配的索引。此方法可以接受参数和块
class Array
def index_all(obj = nil)
if obj || block_given?
proc = obj ? ->(i) { self[i] == obj } : ->(i) { yield self[i] }
self.each_index.select(&proc)
else
self.each
end
end
end
require 'test/unit'
class TestArray < Test::Unit::TestCase
def test_index_all
arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
result = arr.index_all('x')
assert_equal [0, 2, 6], result
arr = [100, 200, 100, 300, 100, 400]
result = arr.index_all {|n| n <= 200 }
assert_equal [0, 1, 2, 4], result
end
end
类数组
def index_all(obj=nil)
如果给出obj | |块| U?
proc=obj?->(i) {self[i]==obj}:->(i){yield self[i]}
self.each_index.select(&proc)
其他的
各自
结束
结束
结束
需要“测试/单元”
类TestArray 结果=arr.index\u all{| n | n您是否在寻找逻辑或语法,可以帮助您了解逻辑但不了解语法:)不太熟悉ruby…您可以使用regexp
我猜逻辑和语法都可以:)不确定是否将regex视为不必要的字符串。这是我认为Python的列表理解确实读起来更好的少数情况之一:[i代表i,如果a=='x'],则a在枚举(arr)中]
。a可枚举#查找(elem)会让我感到不舒服
不在ruby stdlib中。不知何故,这会提出合理的功能请求。请注意,这仅在使用带参数的索引时有效,而不适用于块。对于块,接受的解决方案仍然是唯一的方法。感谢这一点。我只为(:each_with_index)找到了arr.enum_。收集{item,index | item='x'?index:nil}。如果{i | i.nil?}
在此之前。@6ftDan如果{i | i.nil?}
=compact
。出于好奇,p在这个例子中做什么?@user5783745p
以“开发人员友好”的方式将表达式的结果打印到屏幕上。在这种情况下:[0,2,6]
@user5783745my_var=p arr.each_index.选择{i|arr[i]=='x'}
可以使用或不使用p
upvoted来实现最合理的实现。其他任何东西都更复杂。我认为公认的答案更简单;arr.size.times==arr.each_index
。只需一个方法调用,而不是两个。但是根据这里添加的基准测试,显然会稍微慢一点?
arr.each_with_index.select { |a,i| a == 'x' }.map &:last
class Array
def index_all(obj = nil)
if obj || block_given?
proc = obj ? ->(i) { self[i] == obj } : ->(i) { yield self[i] }
self.each_index.select(&proc)
else
self.each
end
end
end
require 'test/unit'
class TestArray < Test::Unit::TestCase
def test_index_all
arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
result = arr.index_all('x')
assert_equal [0, 2, 6], result
arr = [100, 200, 100, 300, 100, 400]
result = arr.index_all {|n| n <= 200 }
assert_equal [0, 1, 2, 4], result
end
end