2009-07-24 6 views
1

Le | m, k | Ce genre de choses me rejette. Est-ce que cela a quelque chose à voir avec l'ordre de préséance? m pour 0 (ou 1 dans certaines langues) et k pour le dernier dans le tableau/Hash?Alors peut-être que je n'ai pas l'idée en Ruby mais j'ai une question à propos de Enumerables injecter

Alors, pourquoi les gens mettent un nombre dans .inject()?

Ou bien, y a-t-il un moyen facile d'apprendre comment l'utiliser, et quelle est sa valeur? A en juger par cette question, j'espère que vous savez tous que je ne suis pas très familier avec les langages de programmation et que Ruby était mon premier choix.

+1

Avez-vous un exemple particulier que vous » d aimer expliquer? La réponse de kjfletch est bonne si vous développez votre question un peu les gens pourraient être en mesure de fournir plus de détails. – mikej

Répondre

1

Les paramètres | x, y | sont utilisés lors de l'utilisation de blocs. Lorsque l'instruction yield est appelée, vous lui indiquez de mettre en correspondance les variables appelantes avec x et y.

Regardez ici Blocks and Yield

Voir ici pour un appel breakdown of an inject().

5

Vous semblez confondre les arguments de bloc avec les arguments de méthode.

Le nombre de personnes passées dans la méthode inject() est un argument de méthode qui détermine la valeur initiale de "m" lorsque vous utilisez | m, k | pour le bloc. Je ne sais pas où vous les avez vus nommés m et k, ou pourquoi ils ont été nommés ainsi, mais ce n'est certainement pas parce qu'ils représentent le premier et le dernier élément.

Il serait plus simple de le regarder de la manière décrite dans le lien de kjfletch, breakdown of an inject(), où ils sont nommés "résultat" et "élément" à la place.

La valeur d'utilisation de injecter() est la capacité à être concis. Tout ce que vous voulez faire avec inject() peut également être fait avec un appel à la méthode each(), avec un bloc beaucoup plus long, et des déclarations de variables supplémentaires. Voir this question and the answer pour avoir une idée de cela.

6

Essayons un exemple.

numbers = [ 3, 1, 4, 1, 5, 9 ] 
sum = numbers.inject(0) do |prefix_sum, number| 
    prefix_sum + number 
end 

#inject prend un argument et un bloc. Le bloc doit prendre deux valeurs et renvoyer une nouvelle valeur. Dans l'exemple ci-dessus, l'argument #inject est 0 et le bloc est do |prefix_sum, number| prefix_sum + number end. Les valeurs qui seront transmises au bloc sont nommées entre les deux marqueurs |: prefix_sum et number.

Chaque valeur de l'élément énumérable #inject est transmise comme seconde valeur au bloc à son tour. Dans cet exemple number sera 3, puis 1, puis 4, puis 1, puis 5, puis finalement 9. Donc, dans cet exemple, le bloc sera invoqué six fois; une fois pour chaque position dans numbers.

La première valeur passée à un bloc (ici nommé prefix_sum) est généralement appelée accumulateur . Sa valeur initiale, la valeur utilisée la première fois que le bloc est appelé par #inject, est définie par l'argument passé à #inject (dans cet exemple, 0). La valeur de retour du bloc détermine la valeur de l'accumulateur (prefix_sum) pour l'appel suivant du bloc.

Lorsqu'il n'y a plus d'éléments à traiter, la valeur de l'accumulateur est renvoyée (et stockée ici dans sum).

permet donc marcher à travers elle:

  • #inject reçoit 0 et notre bloc.
  • #inject invoque notre bloc, la liaison prefix_sum-0 (la valeur initiale de l'accumulateur) et number-3 (la première valeur de tableau). Notre bloc calcule 0+3 comme 3 et le renvoie.
  • #inject invoque notre bloc, la liaison prefix_sum-3 (la valeur retournée) et number-1 (la seconde valeur de tableau)
  • notre bloc calcule 3+1 comme 4 et le renvoie.
  • #inject invoque notre bloc, la liaison prefix_sum-4 (la valeur retournée) et number-4 (la troisième valeur de tableau)
  • notre bloc calcule 4+4 comme 8 et le renvoie.
  • #inject invoque notre bloc, la liaison prefix_sum-8 (la valeur retournée) et number-1 (la quatrième valeur de tableau)
  • notre bloc calcule 8+1 comme 9 et le renvoie.
  • #inject invoque notre bloc, la liaison prefix_sum-9 (la valeur retournée) et number-5 (la cinquième valeur de tableau)
  • notre bloc calcule 9+5 comme 14 et le renvoie.
  • #inject notre bloc invoque, la liaison prefix_sum-14 (la valeur retournée) et number-9 (la sixième valeur de tableau)
  • notre bloc calcule 14+9 comme 23 et le retourne.
  • car il n'y a plus d'éléments de tableau, #inject renvoie 23 et nous lier sum pour être cette valeur.

Vous pouvez regarder Injecter parenthèse une opération sur une liste d'éléments, dans cet exemple, caluculating:

((((((0 + 3) + 1) + 4) + 1) + 5) + 9) 

Cela vous permet de prendre toute opération qui fonctionne normalement sur une paire d'arguments, et l'appliquer à une liste.

+0

+1 excellente explication –

2

Si vous voulez savoir ce que n'importe quelle méthode fait dans Ruby, vous pouvez utiliser l'outil ri fourni (de sorte que vous pouvez taper "ri Enumerable.inject" pour rechercher les docs) ou rechercher Ruby-Doc.Dans ce cas, vous see:

Combine les éléments d'enum en appliquant le bloc à une valeur d'accumulateur (memo) et à chaque élément à tour de rôle. A chaque étape, memo est mis à la valeur renvoyée par le bloc. Le premier formulaire vous permet de fournir une valeur initiale pour le mémo. La deuxième forme utilise le premier élément de la collection comme valeur initiale (et ignore cet élément pendant l'itération).

# Sum some numbers 
(5..10).inject {|sum, n| sum + n }    #=> 45 
# Multiply some numbers 
(5..10).inject(1) {|product, n| product * n } #=> 151200 

# find the longest word 
longest = %w{ cat sheep bear }.inject do |memo,word| 
    memo.length > word.length ? memo : word 
end 
longest           #=> "sheep" 

# find the length of the longest word 
longest = %w{ cat sheep bear }.inject(0) do |memo,word| 
    memo >= word.length ? memo : word.length 
end 
longest           #=> 5 
0

complet: m signifie généralement mémo; k peut signifier la clé (souvent utilisée conjointement avec v, ce qui signifie valeur). Ainsi, par exemple:

stuff.inject({}) { |m,(k,v)| m.merge(k.to_sym => v) } 

J'ai aussi vu des gens utiliser un pour accumulateur et e pour l'élément, comme ceci:

numbers.inject { |a,e| a+e } 
Questions connexes