programing

주어진 조건과 일치하는 요소의 인덱스 찾기

nasanasas 2020. 12. 7. 08:12
반응형

주어진 조건과 일치하는 요소의 인덱스 찾기


배열이 주어지면 주어진 조건과 일치하는 요소의 모든 인덱스를 어떻게 찾을 수 있습니까?

예를 들어 다음과 같은 경우 :

arr = ['x', 'o', 'x', '.', '.', 'o', 'x']

항목이있는 모든 인덱스를 찾으려면 x다음을 수행 할 수 있습니다.

arr.each_with_index.map { |a, i| a == 'x' ? i : nil }.compact   # => [0, 2, 6]

또는

(0..arr.size-1).select { |i| arr[i] == 'x' }   # => [0, 2, 6]

이것을 달성하는 더 좋은 방법이 있습니까?


루비 1.9 :

arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
p arr.each_index.select{|i| arr[i] == 'x'} # =>[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)

each_with_index.map라인에 대한 약간의 개선

arr.map.with_index {|a, i| a == 'x' ? i : nil}.compact # => [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]

AGS의 벤치 마크는이 솔루션과 함께

arr = 10000000.times.map{rand(1000)};

puts Benchmark.measure{arr.each_with_index.map { |a, i| a == 50 ? i : nil }.compact}
puts Benchmark.measure{(0..arr.size-1).select { |i| arr[i] == 50 }}
puts Benchmark.measure{arr.map.with_index {|a, i| a == 50 ? i : nil}.compact}
puts Benchmark.measure{arr.each_index.select{|i| arr[i] == 50}}
puts Benchmark.measure{arr.size.times.select {|i| arr[i] == 50}}
puts Benchmark.measure{arr.find_each_index 50}

  # 1.263000   0.031000   1.294000 (  1.267073)
  # 0.843000   0.000000   0.843000 (  0.846048)
  # 0.936000   0.015000   0.951000 (  0.962055)
  # 0.842000   0.000000   0.842000 (  0.839048)
  # 0.843000   0.000000   0.843000 (  0.843048)
  # 0.405000   0.000000   0.405000 (  0.410024)

이것이 개선이라고 생각하는지 아닌지 확실하지 않지만 ( map+ compact)를 필터로 사용 하면 나에게 매우 투박한 느낌이 듭니다. 그것이 목적 select이기 때문에 나는을 사용 하고 내가 관심있는 결과의 일부를 잡습니다.

arr.each_with_index.select { |a,i| a == 'x' }.map &:last

I defined Array#index_all which behaves like Array#index but returns all matched indices. This method can take an argument and block.

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

참고URL : https://stackoverflow.com/questions/13659696/find-indices-of-elements-that-match-a-given-condition

반응형