6
votes

Comment déstructurer une gamme de rubis?

est-il possible d'utiliser la déstructuration dans RUBY pour extraire la fin et commencer à partir d'une plage?

min, max = (1..10)


1 commentaires

Vous devez soit indiquer que vous n'êtes préoccupé par les gammes de deux points ou clarifiez si vous souhaitez que vous souhaitiez max ou dernier , que vous semblez utiliser l'interchangeabilité.


4 Réponses :


4
votes

Le début et la fin? J'utiliserais: xxx

essayer d'utiliser la déstructuration pendant une plage est une mauvaise idée. Imaginez les tailles de la matrice qui pourrait être générée puis jetée, gaspillant le temps et la mémoire de la CPU. C'est un excellent moyen de doser votre propre code si votre gamme se termine par float :: Infinity .


fin n'est pas le même que max : dans 1 ... 10, fin est 10, mais max est 9

c'est parce que start_val ... fin_val est équivalent à start_val .. (find_val - 1) : xxx

max reflète la réalité des valeurs réellement utilisées par RUBY lors de l'itération sur la plage ou le test d'inclusion dans la plage.

à mon avis, fin doit refléter la valeur maximale réelle qui sera considérée dans la plage et non la valeur utilisée à la fin de la définition de la plage, mais je doute Ça va changer sinon il affecterait le code existant.

... est plus déroutant et conduit à une augmentation des problèmes de maintenance afin que son utilisation n'est pas recommandée. < / p>


8 commentaires

plage # min et max ne sont pas identiques que fin et commencent . max convertit réellement le tableau en une plage et obtient le dernier élément AFAIK.


C'est fondamentalement parce que #max peut être appelé comme max (n) {| a, b | Bloc} → Obj .


min et max renvoie le début et la fin de la plage. Il n'y a rien dans la documentation en disant qu'il est converti en une matrice. Si c'était, convertir 1..float :: Infinity Lorsque vous utilisez max ne reviendrait jamais. Ils sont fondamentalement identiques que commencent et fin sauf qu'ils permettent l'utilisation d'un bloc. commence et fin devrait être plus rapide, de regarder la source.


Essayez d'appeler (1..float :: Infinity) .max avec un bloc.


Bien que l'appelant sans bloc ne provoque plus que votre programme explose plus comme dans 1.9.3


@thetinman: Notez que #end n'est pas identique que #max : dans 1 ... 10 , #end est 10 , mais #max est 9 . Dans 10..1 , #end est 1 , mais #max est nil . Vous devez choisir en fonction de votre cas d'utilisation si vous voulez #begin et #end (et #exclude_end? ) ou #min et #max .


Un autre cas spécial: (1 ... 2.5) .max augmente un typeError .


Cela ressemble à un bug.



3
votes

Non, Strike> Jusqu'à ce que je suis prouvé incorrect par Cary Swoveland, une nouvelle mondiale hebdomadaire ou un autre tabloïd, je vais continuer à croire sans aucune preuve que la réponse est "non"; Mais il est assez facile de faire.

module RangeWithBounds
  refine Range do
    def bounds
      [self.begin, self.end]
    end
  end
end

module Test
  using RangeWithBounds
  r = (1..10)
  b, e = *r.bounds
  puts "#{b}..#{e}"
end


13 commentaires

Ne * r contrainte-t-il la gamme dans un tableau?


@max: non, * r.bounds est * (r.bounds) , pas (* r) pots . N'oubliez pas que * n'est pas un opérateur, mais une construction syntaxique dans l'affectation Lvalue, la déclaration d'affectation, la liste des arguments (définition et appel) et le réseau littéral. Cela n'a même pas de priorité, car il ne peut pas être évalué "à l'intérieur" une expression.


Merci, je suppose que cela a plus de sens. Je n'avais jamais envisagé que vous ne pouvez pas faire matry. * comme vous pouvez avec les opérateurs.


Je n'avais pas envisagé d'exclure les gammes non plus que ce qui aurait fait a, b = (1 ... 10) ambigu.


Vous pouvez remplacer [auto.begin, auto.end] avec [premier, dernier] , mais pas avec [COMMENCE, END] " Code> [COMMENCE, DERNIER] ou [PREMIER, END] , AS COMMENCEZ ET FIND Sont des mots réservés. @max, vous pensions peut-être [* 1..4] # => [1, 2, 3, 4] .


@CarySwoveland - No - Casting to Un tableau est exactement ce que j'essayais d'éviter. Je me demandais simplement si Ruby avait une syntaxe pour obtenir les limites d'une gamme - sa plus d'une question théorique que pratique.


@max, ah, je m'adressais au premier commentaire ci-dessus, après avoir manqué le fait que c'est votre question.


Amadan, vous n'avez pas montré de preuves pour "Non" dans votre première phrase. C'est la question, après tout. En outre, limites renvoie un tableau. N'est-ce pas une violation?


Ce n'est pas une coercition de l'objet de la plage. C'est un tableau nouvellement construit de deux éléments. Vous ne pouvez pas faire de multiples retour dans Ruby sans tableaux. Quant à votre première plainte ... quel type de preuves attendez-vous d'un existentiel négatif? Les revendications positives sont prouvées, des revendications négatives sont DIS éprouvées. Si vous voulez une preuve formelle ici, c'est sur vous de me prouver.


"Non" constitue une affirmation. Nous devrions nous attendre à une preuve ou au moins d'arguments pour soutenir les assertions. Si vous ne pouvez pas fournir cela, vous devez préciser que vous donnez une opinion ou que vous soyez muet sur ce point.


@CarySwoveland: Mon opinion n'est qu'aucune syntaxe de ce type n'existe. C'est aussi mon avis que les Leprechuns ne sont pas réels. Je ne peux pas prouver non plus. Cependant, si vous me donnez un contre-exemple, je supprimerai cette réponse comme inexacte et commencerai à suivre les arcs-en-ciel.


Je ne conteste pas que (pas même la référence à Leprechauns ). Je pense juste que vous devriez dire "c'est mon avis ..." plutôt qu'un "non" stérile, alors que les lecteurs peuvent prendre cela comme un fait.


Dans mon commentaire précédent "Vous pouvez remplacer ..." J'ai négligé le fait que max et Dernier ne sont pas équivalents, car Amadan a souligné dans un commentaire sur la réponse de @ thetinman. Mon commentaire ne s'applique qu'aux hachages à deux points.



0
votes

La réponse d'Amadan va bien. Il vous suffit de supprimer la splat (*) lorsque vous l'utilisez car elle n'est pas nécessaire

par exemple, xxx


0 commentaires

4
votes

Vous pouvez utiliser Minmax sur les gammes de destructures: xxx

Si vous utilisez Ruby avant 2.7, évitez d'utiliser ceci sur de grandes gammes.


4 commentaires

Sachez que cela renvoie la valeur minimale et maximale de la plage, pas le début et la fin de la plage.


Sachez également que cela ne gère pas bien les gammes infinies. (- Float :: Infinity..0) .minmax relève TypeError et (0..float :: Infinity) .Minmax Ne retourne jamais valeur.


I.e., MINMAX iTère à travers la plage, tandis que [plage.min, plage.max] ne fonctionne pas et fonctionne bien avec des gammes infinies. Évitez donc Minmax si votre gamme a un nombre énorme (ou infini) d'éléments.


Dans Ruby 2.7, MinMax ne fait plus itérale à travers la gamme et fonctionne bien avec des gammes infinies 🎉 RUBYRERFERENCES.GITUB.IO/RUBYCHANGES//.../A>