5 votes

Pourquoi les convertisseurs CSV::HeaderConverters arrêtent-ils le traitement lorsqu'ils renvoient une valeur autre qu'une chaîne de caractères ?

Pourquoi le traitement des convertisseurs d'en-tête arrêtez avec le premier non String qui est renvoyé par un convertisseur d'en-tête ?

Détails

Après l'intégration :symbol Le convertisseur d'en-tête est déclenché, aucun autre convertisseur ne sera traité. Il semble que le traitement des convertisseurs d'en-tête arrête avec le premier convertisseur qui retourne quelque chose qui n'est pas un String (c.-à-d. le même comportement si vous écrivez un convertisseur d'en-tête personnalisé qui renvoie un fichier Fixnum ou autre).


Ce code fonctionne comme prévu en lançant l'exception dans :throw_an_exception

require 'csv'

CSV::HeaderConverters[:throw_an_exception] = lambda do |header|
  raise 'Exception triggered.'
end

csv_str = "Numbers\n" +
          "1\n" +
          "4\n" +
          "7"

puts CSV.parse(
  csv_str,
  {
    headers: true,
    header_converters: [
      :throw_an_exception,
      :symbol
    ]
  }
)

Cependant, si vous changez l'ordre des convertisseurs d'en-tête de façon à ce que l'option :symbol Le convertisseur vient en premier, le :throw_an_exception lambda n'est jamais appelé.

...

header_converters: [
  :symbol,
  :throw_an_exception
]

...

2voto

jefflunt Points 20244

J'ai donc contacté JEG2 .

Je pensais que les convertisseurs étaient destinés à être une série d'étapes dans une chaîne, où tous les éléments étaient censés passer par cada étape. En fait, ce n'est pas la meilleure façon d'utiliser la bibliothèque CSV, surtout si vous avez une très grande quantité de données.

La manière dont il doit être utilisé (et c'est la réponse à la question "pourquoi"). y l'explication de la raison pour laquelle cela est meilleur pour les performances) est de faire fonctionner les convertisseurs comme une série d'appariements, où le premier convertisseur apparié renvoie un non String qui indique à la bibliothèque CSV que la valeur actuelle a été convertie avec succès. Lorsque vous faites cela, l'analyseur syntaxique peut s'arrêter dès qu'il y a une valeur non String et passer à la valeur d'en-tête/cellule suivante.

De cette façon, vous supprimez une tonne de frais généraux lors de l'analyse des données CSV. Plus le fichier que vous traitez est volumineux, plus vous éliminez de frais généraux.

Voici la réponse que j'ai reçue par courriel :

...

Les convertisseurs sont essentiellement un pipeline de conversions à essayer. Disons que vous utilisez deux convertisseurs, un pour les dates et un pour les nombres. Sans ligne liée, nous essayerions les deux pour chaque champ. Cependant, nous savons deux choses :

  • Un champ CSV non converti est un champ de type String parce que c'est comme ça que nous l'avons lu dans
  • Un champ qui est maintenant un non String a été converti, nous pouvons donc arrêter de chercher un convertisseur qui correspond.

Étant donné que l'optimisation permet à notre exemple de ne pas vérifier le convertisseur de nombres si nous avons déjà un Date objet.

...

1voto

mudasobwa Points 5530

Pour une raison inconnue CSV#convert_fields a une fonction hilarante

break unless field.is_a? String # short-circuit pipeline for speed

ligne dans converters.each . Je doute pouvoir suggérer quelque chose de mieux que de monkeypatching cette fonction, mais la cause est claire maintenant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X