2012-03-29 9 views
1

ich nach einer Möglichkeit, die folgenden in Ruby in eine sauberere Art und Weise zu tun:Rubin in Array finden mit Offset

class Array 
    def find_index_with_offset(offset, &block) 
    [offset..-1].find &block 
    end 
end 

offset = array.find_index {|element| element.meets_some_criterion?} 
the_object_I_want = 
    array.find_index_with_offset(offset+1) {|element| element.meets_another_criterion?} 

Also ich suche ein Ruby-Array für den Index eines Objekts und dann Ich mache eine Nachfolgesuche, um das erste Objekt zu finden, das einem anderen Kriterium entspricht und einen höheren Index im Array hat. Gibt es einen besseren Weg, dies zu tun?

Was meine ich mit cleaner: etwas, das nicht explizit das Array in Scheiben schneiden. Wenn Sie dies ein paar Mal tun, wird die Berechnung der Slicing-Indizes schnell unordentlich. Ich würde gerne auf dem ursprünglichen Array weiterarbeiten. Es ist einfacher zu verstehen und weniger fehleranfällig.

NB. In meinem eigentlichen Code habe ich nicht affen gepatcht Array, aber ich möchte die Aufmerksamkeit auf die Tatsache lenken, dass ich ich bin duplizieren vorhandene Funktionalität von Array/Enumerable


Edits

  • Fest erwarten Lage von offset + 1 laut Aussage von Mladen Jablanović; umschreiben Fehler
  • Added Erklärung von ‚sauberere‘ gemäß Mladen Jablanović Kommentar
+0

Was meinst du mit "Reiniger"? Was stört dich mit deiner Lösung? Die Tatsache, dass '[]' ein neues Array erstellt? Oder nur die Ästhetik? –

+0

Übrigens, ich denke, Sie sollten innerhalb von '[offset ..- 1]' suchen und stattdessen '(offset + 1) 'an den Methodenaufruf übergeben. Es ist logischer als IMO. –

+0

Einfache Schleife ist sauberer, wenn Sie das Schneiden vermeiden möchten –

Antwort

2

Reiniger hier offensichtlich subjektive Angelegenheit. Wenn Sie kurz sind, glaube ich nicht, dass Sie es besser machen könnten. Wenn Sie an die Kette mehrere derartige Funde in der Lage sein wollen, oder Sie werden durch Aufschneiden gestört, können Sie etwas tun:

module Enumerable 
    def find_multi *procs 
    return nil if procs.empty? 
    find do |e| 
     if procs.first.call(e) 
     procs.shift 
     next true if procs.empty? 
     end 
     false 
    end 
    end 
end 


a = (1..10).to_a 
p a.find_multi(lambda{|e| e % 5 == 0}, lambda{|e| e % 3 == 0}, lambda{|e| e % 4 == 0}) 
#=> 8 

Edit: Und wenn Sie nicht besorgt über die Leistung, die Sie etwas tun könnte, wie :

array.drop_while{|element| 
    !element.meets_some_criterion? 
}.drop(1).find{|element| 
    element.meets_another_criterion? 
}