2009-11-10 6 views
3

Y a-t-il un composant Array ou Enumerable intégré qui me permet de rechercher un élément à l'aide d'un bloc et de renvoyer son index?Comment utiliser index ou rindex avec un bloc dans Ruby?

Quelque chose le long des lignes de:

ar = [15,2,33,4,50,69] 
indexes = ar.find_indexes {|item| item > 4 == 0} 
# indexes will now contain 0,2,4,5 

Il serait très facile d'ajouter mon propre, mais je voudrais savoir si cela existe déjà?

Répondre

7

Je ne pense pas qu'il y ait quoi que ce soit intégré, au moins je n'ai pas remarqué quoi que ce soit non détectés auparavant dans les Array ou Enumerable docs.

C'est assez laconique, cependant:

(0..ar.size-1).select { |i| ar[i] > 4 } 

EDIT: Aurait mentionné c'est Ruby 1.8.6.

AUTRE EDIT: oublièrent triple point, ce qui permet d'économiser un caractère entier, ainsi que le nettoyage du -1, que je n'étais pas à l'aise avec:

(0...ar.size).select { |i| ar[i] > 4 } 
3

Je comprends que ce n'est que Ruby 1.9

indexes = ar.collect.with_index { |elem, index| index if elem > 4 }. 
      select { |elem| not elem.nil? } 

EDIT: pour Ruby 1.8 essayer

require 'enumerator' 
indexes = ar.to_enum(:each_with_index). 
      collect { |elem, index| index if elem > 4 }. 
      select { |elem| not elem.nil? } 
+0

'xs.select {| élém | pas elem.nil? } '->' xs.compact' – tokland

0

Il est essentiellement Mike Woodhous La réponse de e a été reformatée pour supprimer la gamme laide.

ar.each_index.select{|item| item > 4} 

est ici une version de la réponse de johnanthonyboyd qui fonctionne avec Ruby 1.8.7

ar.enum_with_index.each.select{|item| item.first > 4}.map(&:last) 
+0

Vous ne pouvez pas voir comment la chose [each_index] (http://ruby-doc.org/core/classes/Array.html#M002174) fonctionne - il faudrait retourner un Enumerable , n'est-ce pas? enum_with_index semble utile, mais il convient de noter qu'il ne fait que 1.8.7 et plus, tout comme la chose pratique map (&: ...) (en dehors de Rails). En outre, les docs suggèrent qu'il nécessite 'require énumérateur'. Je suis toujours en 1.8.6, donc je ne peux pas vérifier. –

+0

Chaque méthode each_index et autre itérateur renvoie l'objet Enumerable traversé par iterator. Quant à la syntaxe de l'autre, elle a fonctionné dans mon local irb install (en utilisant ruby ​​1.8.7, je n'avais pas réalisé qu'il s'agissait d'une addition récente) – EmFi

+0

Je suppose que vous vouliez dire: 'ar.each_index.select {| idx | ar [idx]> 4} ' – tokland

1

Il suffit de laisser exploser la puissance de la méthode d'injection !!! ;-)

ar.inject([]){|a,i| a.empty? ? a << [0, i] : a << [a.last[0]+1,i]} 
    .select{|a| a[1] > 4} 
    .map{|a| a[0]} 

(fonctionne avec rubis 1.8.6)

+0

Celui-ci devrait être un plaisir à déboguer. – Geo

+0

Bien sûr, mais heureusement, il n'y a pas besoin de déboguer;) – Erlock

+0

Il ne l'est jamais. Jusqu'à ce qu'il y en ait :) – Geo

1

Non, mais vous pouvez toujours patcher singe si vous voulez:

class Array 
    def find_indexes(&block) 
    (0..size-1).select { |i| block.call(self[i]) } 
    end 
end 

ar = [15,2,33,4,50,69] 
p ar.find_indexes {|item| item > 4 } #=> [0, 2, 4, 5]               
+0

Ouais, je sais que c'est une option, mais je pensais que peut-être quelque chose d'équivalent existait déjà. – Geo