2012-12-01 12 views
47

एक सरणी को देखते हुए, मैं किसी दिए गए शर्त से मेल खाने वाले तत्वों के सभी सूचकांक कैसे प्राप्त कर सकता हूं?किसी दिए गए शर्त से मेल खाने वाले तत्वों के सूचकांक खोजें

उदाहरण के लिए, अगर मेरे पास है:

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] 

वहाँ एक है इसे हासिल करने के लिए अच्छा तरीका?

+0

, आप तर्क या वाक्य रचना की तलाश कर रहे हैं तर्क के साथ मदद कर सकता है लेकिन नहीं वाक्यविन्यास यद्यपि :) माणिक से परिचित नहीं ज्यादा ... तुम एक 'regexp' – bonCodigo

+0

मैं दोनों तर्क और वाक्य रचना लगता है कि उपयोग कर सकते हैं :) रेगेक्स के बारे में निश्चित नहीं है क्योंकि आइटम आवश्यक तार नहीं हैं। –

+0

यह उन कुछ मामलों में से एक है जहां मुझे लगता है कि पाइथन की सूची की समझ वास्तव में बेहतर पढ़ती है: '[i i i, a enumerate (arr) अगर कोई ==' x '] '। बेंचमार्क –

उत्तर

64

रूबी 1.9 से अधिक एक मामूली सुधार:

arr = ['x', 'o', 'x', '.', '.', 'o', 'x'] 
p arr.each_index.select{|i| arr[i] == 'x'} # =>[0, 2, 6] 

Code

+1

इसके लिए धन्यवाद। मुझे केवल 'arr.enum_for (: each_with_index) मिला था। {Select, | item | index | आइटम == 'एक्स'? अनुक्रमणिका: शून्य} .delete_if {| i | i.nil? } इससे पहले। –

+3

@ 6ftDan 'delete_if {| i | i.nil? } '==' कॉम्पैक्ट'। – steenslag

+0

अच्छा और बेवकूफ – ki4jnq

19

एक और तरीका है:

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) 
+3

+1 सबसे उचित कार्यान्वयन के लिए अपवित्र। और कुछ और जटिल है। – Sheharyar

+0

के लिए – akostadinov

10

अपने each_with_index.map लाइन

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

यह तरीकों थोड़ा अधिक समय लेकिन जितनी जल्दी दोगुना है

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) 
+0

नोट यह केवल पैरामीटर के साथ इंडेक्स का उपयोग करते समय काम करता है, न कि ब्लॉक के साथ। एक ब्लॉक के लिए, स्वीकार्य समाधान अभी भी एकमात्र तरीका है। – Sprachprofi

4

सुनिश्चित नहीं हैं कि अगर आप इस एक सुधार है या नहीं, लेकिन का उपयोग कर (map + compact पर विचार इस समाधान के साथ campared) एक फिल्टर के रूप में मुझे बहुत गुस्सा लगता है। मैं, select का प्रयोग करेंगे के बाद से है कि क्या इसके लिए है, और फिर बस परिणाम का हिस्सा मुझे परवाह के बारे में हड़पने:

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

मैं 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 
संबंधित मुद्दे