1
votes

Le moyen le plus concis de diviser un tableau?

String a la méthode intégrée .split () mais Array ne l'a pas. Pourquoi?

Le mieux que je puisse faire est:

['(', 'name:', 'John', 'Deer', ')', '(', 'name:', 'Jane', 'Doe', ')']
  .split(/\(|\)/);

// [['name:', 'John', 'Deer'], ['name:', 'Jane', 'Doe']]
Array.prototype.split = function(separator) {
  return this.toString().split(separator)
    .map(egg => egg.split(',')
      .filter(Boolean))
    .filter(egg => egg.length);
}

Y a-t-il une manière plus concise d'écrire ceci, ou plus efficace à faire pour le cas général ?


5 commentaires

Si les tableaux avaient une méthode nommée split , je ne m'attendrais pas du tout à ce que cela fonctionne de cette façon. De plus, au lieu d'ajouter des méthodes aux éléments intégrés, il est préférable de créer simplement une fonction utilitaire


Comment pensez-vous que cela fonctionne? Le fractionnement d'une String aboutit à un tableau de chaînes, il me semble donc logique que le fractionnement d'un Array aboutisse à un tableau de tableaux.


Étant donné que les tableaux sont des collections de valeurs de type arbitraire, je m'attendrais à ce qu'il se comporte d'une manière indépendante du type de ces valeurs et ne les convertisse pas automatiquement en chaînes.Personnellement, je m'attendrais à une sorte de segmentation ou de partitionnement.


['bonjour, monde', '3/4', '/', 0.7, '1,2,3'] .split ('/') retournerait? Pas ce à quoi on pourrait s'attendre. Je suis d'accord avec @AluanHaddad, le fractionnement doit correspondre à un élément, pas à une chaîne une fois le tableau converti en chaîne. Le résultat de mon exemple devrait être [['hello, world', '3/4'], [0.7, '1,2,3']]


@AustinFrance, c'est définitivement une possibilité intéressante. Cela semble encore trop spécifique à l'ajout d'un membre au tableau


3 Réponses :


2
votes

à quoi cela ressemble:

function GroupAt( separator, array ){
        const regString = (separator).toString().replace(/^\/|\/g?i?$/g, '').replace(/\\/, "\\");
    
        return (array)
            .join(',')
            .replace( new RegExp( "^"+regString+"\\,|\\,"+regString+"$", 'g' ), '')
            .replace( new RegExp( '(,?'+ regString +',?){1,}', 'g' ), regString)
            .split(regString)
            .map(str => str.split(','))     
    
    }
const sample = ['(', 'name:', 'John', 'Deer', ')', '(', 'name:', 'Jane', 'Doe', ')'];

console.log(GroupAt(/[\(\)]/g, sample))
console.log(GroupAt( /(\(|\)|John)/g, sample ))

ou

function GroupAt( separator, array ){
    return (array)
        .join(',')
        .replace( separator, ',')
        .replace( /^\,{1,}|\,{1,}$/g, '')
        .split( /\,{2,}/ )
        .map(str => str.split(','))     

};

const sample = ['(', 'name:', 'John', 'Deer', ')', '(', 'name:', 'Jane', 'Doe', ')'];

console.log(GroupAt(/[\(\)]/g, sample))
console.log(GroupAt( /(\(|\)|John)/g, sample ))

UPDATE 1 (shortend)

(['(', 'name:', 'John', 'Deer', ')', '(', 'name:', 'Jane', 'Doe', ')'])
  .join(',')
  .match(/\,?\(\,?(.*?)\,\)\,?/g)
  .map( str => str.replace(/\,?[\(\)]\,?/g, '').split(',') );


2 commentaires

C'est utile pour mon cas d'exemple mais ce n'est pas une fonction qui fonctionne pour tous les cas en général. String.split permet d'utiliser des séparateurs à plusieurs caractères, mais comment diviser un Array fonctionnerait-il avec des séparateurs à plusieurs éléments?


depuis que vous l'avez demandé, j'ai ajouté la suite logique de l'exemple suggéré à transformer en fonction, mais je ne peux toujours pas placer la nécessité générale de if, plutôt qu'un cas d'utilisation spécifique. Existe-t-il un bon exemple pour illustrer l'idée derrière la généralisation sur un tableau, certains éléments étant un séparateur? Voulez-vous dire que les éléments de séparation du tableau doivent correspondre à votre requête du début à la fin ou qu'une correspondance partielle doit être acceptée?



1
votes

Êtes-vous sûr de ne pas essayer de créer un tokenizer?

En voici un naïf:

[ [ 'name:', 'John', 'Deer' ], [ 'name:', 'Jane', 'Doe' ] ]

La valeur résultante est:

XXX

Voici quelque chose que j'ai recherché pour vous: https://www.freecodecamp.org/news/how-to-build-a-math-expression-tokenizer-using-javascript-3638d4e5fbe9/ p>

Aussi, une citation de Jamie Zawinski:

Certaines personnes, confrontées à un problème, pensent "Je sais, je vais utiliser des expressions régulières". Maintenant, ils ont deux problèmes.


0 commentaires

1
votes

La conversion en chaîne est problématique. Les éléments doivent être testés comme des éléments et non lorsqu'ils sont combinés avec d'autres éléments. Considérez le tableau:

[ [ 'hello, world', '3 / 4' ], [ 0.7, '1,2,3' ] ]
[ [ 'hello, world', '3 / 4', '/' ], [ '1,2,3' ] ]
[ [ '3 / 4', '/', 0.7, '1,2,3' ] ]
[ [ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ] ]
[]

Voici une solution qui n'utilise pas de conversion de chaîne, sauf lors de la comparaison d'un élément individuel. Prend également en charge les expressions régulières.

console.log([ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ].split('/'));
console.log([ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ].split(0.7));
console.log([ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ].split(/^hello/));
console.log([ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ].split(/^hello$/));
console.log([ ].split(1));

Tests:

Array.prototype.split = function(sep) {
  return this.reduce((acc, v, i) => {
    if (v == sep || (sep.exec && sep.exec(v))) acc.push([]);
    else {
      if (i == 0) acc.push([]);
      acc[acc.length-1].push(v);
    }
    return acc;
  }, []);
}

Résultat:

[ 'hello, world', '3 / 4', '/', 0.7, '1,2,3' ]


0 commentaires