Je dois écrire une fonction qui teste, si la chaîne est donnée est "vide" dans un sens qu'il contient uniquement des caractères d'espaces. Les caractères d'espaces sont les suivants: La fonction sera appelée beaucoup de fois, de sorte que cela doit être vraiment, vraiment performant. Mais ne devrait pas prendre trop de mémoire (comme cartographier tous les caractères sur TRUE / FAUX dans un tableau). Choses que j'ai essayées jusqu'à présent: p> Ma solution actuelle utilise des comparaisons codées: p>
si (! Whitespacecharactersmap [str [index]]]) ... code>) - fonctionne assez bien li>
var re = /[^\s]/;
return !re.test(str);
3 Réponses :
solution codée dur semble le meilleur, mais je pense que commutateur code> devrait être plus rapide. Cela dépend de la façon dont JavaScript Interprète gère ceux-ci (la plupart des compilateurs le font très efficacement), de sorte qu'il for (var index in str)
{
...
}
Javascript a une déclaration foreach?
@Basilikum Mine ne peut-être pas, peut-être ES6?
Ma faute. Doit être " pour code> utilisé comme foreach code> dans php". Drôle, quand j'ai testé, j'ai utilisé pour code>.
Utilisation de Var Index dans Str code> Pour itérer sur une chaîne est la pire idée de cette réponse.
Pourquoi? Les itérateurs ne sont-ils pas censés être rapides?
Et aussi, cette solution semble manquer le VRAI code>, au cas où il n'y a vraiment que des espaces bleus. Jusqu'à présent, il retournera toujours faux code> ou je manque quelque chose?
Ceci est la partie test du code. Je suppose que l'OP peut ajouter l'en-tête et le pied de page par lui-même (je n'ai pas non plus (re) définir longueur code>).
Ce test (sans changement de pour code>) a fait plusieurs fois fois b> plus vite que les autres: jsperf.com/hash-with-comparisons/3 (testé sur chrome et Seamonkey).
Voici le démontage V8 (JS utilisé dans chrome et Node.js) pour la fonction de commutation, a l'air très serré Pastebin.com/krk3hcdh . Il a également été inliné quand appelé.
Attribué à la Bounty - Approche globale Des tests JSPERF. Merci!
Merci beaucoup. Cependant, notez que dans Révision 6 Le test sans succursale semble mieux dans FF et Chrome, tandis que Safari nécessiterait une version distincte à base de regex.
@ Vedranšego Oui, je sais, j'ai fait la révision 6. C'est pourquoi j'ai choisi de regex après tout.
Depuis que la ramification est beaucoup plus chère que la plupart des autres opérations, vous voulez garder des succursales au minimum. Ainsi, votre séquence de déclarations if / else peut ne pas être très performante. Une méthode qui utilise plutôt la plupart des mathématiques serait beaucoup plus rapide. Par exemple:
Un moyen d'effectuer une vérification d'égalité sans utiliser de ramification consiste à utiliser des opérations binaire. Un exemple est, pour vérifier que A == B: p> puisque le xor de deux bits similaires (c'est-à-dire 1 ^ 1 ou 0 ^ 0) est 0, xor- Deux valeurs égales produisent 0. Ceci est utile car cela nous permet de traiter 0 comme une "vraie" valeur et de faire plus de mathématiques. Imaginez que nous avons une bande de variables booléennes représentées de cette manière: les numéros non nul sont faux, et zéro signifie vrai. Si nous voulons demander: "Est-ce que l'un de ces vrais?" Nous les multiplierons simplement tous ensemble. Si l'un d'entre eux était vrai (égal à zéro), tout le résultat serait zéro. P> Donc, par exemple, le code ressemblerait à ceci: P> if ((c == '\u0009') || (c == '\u000A') || (c == '\u0008') ...)
Ça sonne assez bien; La pratique est beaucoup moins convaincante.
Vous voulez dire que les trucs sur la logique courte circuits et la ramification sont chères? Oui. Il peut être un peu plus complexe dans une langue de haut niveau comme JS, mais il est définitivement vrai du code dirigé directement sur le processeur (avec comparaison de la langue de montage et instructions de saut conditionnel). J'imagine que c'est probablement vrai de JS dans un contexte compilé également, et Chrome compile son JS, donc probablement. Ce n'est certainement pas plus lent.
Il est plus lent. Faire des hypothèses sur la façon dont les langues JIT fonctionnent sur la logique du processeur ne vous mèneront pas loin.
Hein, intéressant, @ Raina777Aw; Je n'aurais pas attendu que. Je me demande si c'est une optimisation du compilateur, ou peut-être que le court-circuit économise suffisamment d'opérations pour le rendre valable. Ou peut-être qu'il fait branler dans les deux cas et n'est pas assez proche pour le matériel pour faire la différence.
"Oui. Il peut être un peu plus complexe dans une langue de haut niveau comme JS, mais il est définitivement vrai du code exécuté directement sur le processeur (avec comparaison de la langue de montage et instructions de saut conditionnel). J'imagine que c'est probablement vrai de JS dans un contexte compilé également et chrome compile son JS, donc probablement. " Votre imagination et vos suppositions ne sont pas soutenues par une expertise. -1 Pour afficher une analyse détaillée dans la mauvaise langue et non justifier pourquoi elle s'applique ici, au-delà de la devinette.
La théorie a raison et cela fonctionnera de loin le plus rapide si Math.imul code> est ajouté . Le problème pour l'instant est que * code> ne peut pas faire de multiplication entier correctement dans ce cas. Voici un code incorrect qui fonctionne bien (de loin les moins les plus rapides) car il n'y a pas de frais générale de convertir constamment entre les entiers et les doubles jsperf.com/hash-with-comparisons/5 . La seule différence est que V8 et SpiderMonkey peuvent déduire une multiplication entière correctement dans cette situation.
Si JavaScript ait Bit Xor (^), il a sûrement un peu et (&?). Donc, "et" les éléments xor-ed ensemble plutôt que de multiplier.
Bonne pensée, @irabaxter. Une modification, bien que: vous voudriez ou (|) les éléments ensemble. VRAI est représenté par 0, et FALSE par 1, afin de voir si l'un d'entre eux est faux, ou tous ensemble, et vous verrez s'il y avait un 1 bit partout dans la chaîne.
Oui, tu avais raison, @irabaxter. Je viens de courir le test avec le bitwise-ou, et cela allait d'environ 20k ops / sec à ~ 22k ops / sec. Juste sur :). jsperf.com/hash-with-comparisons/8
Heureux d'aider, d'une manière en arrière: -}
Ceci crée et utilise une recherche "hash 'sur les caractères de la chaîne, s'il détecte un espacement non-blanc, puis renvoie false: pas sûr de sa performance EDIT: P> < P> Il semble que la solution que vous devriez aller avec peut-être probablement dépendra probablement de la nature des données avec lesquelles vous travaillez: est-ce que les données sont principalement des espaces ou essentiellement non-blouses? Aussi le texte d'ASCII-gamme? Vous pourrez peut-être accélérer les cas de test moyens en utilisant des contrôles de plage (via Peut-être quelque chose comme ceci (un hybride de si / commutateur / hachage) pourrait fonctionner: p> ( pourtant) frappe>. Après un test rapide sur JSperf, il s'avère être assez lent que REGEXP à l'aide de / ^ \ s * $ / code>. P>
si code>) pour des gammes de caractères communes non-blouses, à l'aide d'un commutateur code> sur le blanc le plus courant, Ensuite, utilisez une recherche de hachage pour tout le reste. Cela améliorera probablement la performance moyenne des tests si la plupart des données testées sont composées des caractères les plus courants (entre 0x0--0x7f). P>
Pourquoi voudriez-vous croire qu'une instruction de commutation est plus rapide qu'une opération d'index de matrice? Je serais vraiment surpris si votre "hybride" était plus rapide que votre table de recherche originale. Je serais également tenté de faire la table de recherche dense, c'est-à-dire remplir toutes les entrées i> avec true ou false. L'interprète JS peut mettre en œuvre la matrice dans les coulisses avec un filet de discrimination. (Il peut également utiliser une table de hachage, à quel point votre solution est probablement la meilleure).
@Ira Baxter. Je pense que vous avez raison sur indexof code> être beaucoup plus rapide. Les déclarations de commutation ont un peu plus d'opérations que la plupart des gens se rendent compte pour adhérer aux normes: ( ECMAScript: relevé de commutation ). En ce qui concerne la table de hachage, il s'agit toujours d'une opération relativement coûteuse, mais pour le texte normal ASCII-gamme, la recherche hachage ne devrait pas se produire (d'où le si code> et commutateur code> était utilisé pour capturer la majorité des cas).
"Indice de"? Je n'ai rien dit sur Indexof. Je m'attendais simplement à une recherche directe dans un tableau dense à assez rapide et ne contient aucune branche (ou d'autres conversions implicites / shenanigans de la part du commutateur).
@Ira Baxter C'est la capture, si je ne me trompe pas, obtenir un élément d'un tableau via l'index n'est pas différent d'obtenir une propriété d'un objet via une clé en ce qui concerne la performance (pourrait dépendre du navigateur). C'est une «fonctionnalité» de JavaScript.
PHP était comme ça aussi jusqu'à ce qu'ils (il y a longtemps) ont compris que l'indexation de la matrice valait la peine de faire de la peine pour des raisons de performance. Dans le grand schéma des choses, c'est un très petit changement à l'interpréteur / gigue JavaScript avec une grande gaieté, en particulier. Compte tenu de l'intérêt croissant pour la performance javascript ces jours-ci. Êtes-vous Assurez-vous que I> cet index de tableau sur Les tableaux denses i> sont effectués en effectuant une recherche de propriété (par exemple, «hachage») sur la valeur indice de tableau?
Je ne sais pas grand chose à propos de JS ... que diriez-vous d'une expression régulière?
Vous pouvez passer beaucoup de temps à optimiser des choses qui ne valent pas la peine. Test simple
string.match (/ ^ \ s * $ / ') code> fera parfaitement le travail dans Très peu de temps ...Vous pouvez également utiliser
si (ligne.trim (). ISPTY ()) {// ligne est "vide"} code> de Stackoverflow.com/questions/3012788/... Trim () n'est pas bon car il crée une version trimérique de la chaîne. Ce que je n'ai pas besoin, même temporairement.
Pouvez-vous donner la source de
50-100% plus rapide code>? Mes expériences montrent Le contraire . Vous n'avez pas recréé ce hachage avec chaque appel de fonction, non?@Tomas s'il le veut hyperoptimisé, le regex n'est guère de la voie. Même alors,
var re = / ^ \ s * $ /; code> quelque part dans le corps principal, puisstring.match (re) code> où il a besoin, il sera significativement meilleur, Comme il ne recrée pas la regex à chaque fois qu'elle s'appelle.Selon UNICODE 6.2 et ECMAScript 5 Mise en œuvre d'expressions régulières, seul
\ ufeff code> est détecté lorsqu'il ne devrait pas, et\ u0085 code> non détecté quand il devrait être.Il ne dispose pas de certains des cas de test que vous avez essayés encore, mais de les brancher dans JSPERF - Vérifiez si une chaîne contient uniquement WhitSpace aidera les autres à vérifier vos algorithmes et tests de test. Cela aidera également quelqu'un d'autre à venir pour un problème similaire.
Vous attendez-vous vraiment aux utilisateurs de chasser les caractères d'Espace obscure pour remplir vos champs et mettez-vous ainsi votre utilité au travail? ... Ou êtes-vous vraiment en train de vérifier si un champ contient un contenu requis i> Chèque? Cela ressemble à vous essayer de résoudre un problème le moyen difficile de couvrir que 0,001% de coins d'angle où quelqu'un essaie de tracer les ordures. Je suppose que cela serait plus facile de le nettoyer ultérieurement avec un SQL rapide et rapide Requête après le fait ... tous les 6 mois environ.
@scunliffe +1, conseil très pratique. Ce qui m'intéresse est le raisonnement des exigences supplémentaires pour cette fonction particulière d'être rapide: il sera appelé beaucoup de fois i>. Mais si on traite, comme, des matières de différentes chaînes i> (dans un contexte unique), quelque chose me dit que cette méthode particulière est le dernier goulot d'étranglement potentiel.
@Tomas: cependant, la mise en cache de la regex et de l'utilisation de
code> est considérablement plus rapide: Jsfiddle.net / Rxrba / 1