1
votes

Existe-t-il un moyen de transformer une chaîne en fonction de la ligne de texte ci-dessus?

J'ai une longue liste de tableaux qui comprend des lignes de genre (commencez par des lettres majuscules comme: ACHNANTHES) et des lignes d'espèces (commencez par une lettre majuscule en premier et un point comme: A.) je dois transformer une petite partie, comme ci-dessus texte. Ci-dessous, vous pouvez facilement comprendre:

array (
  0 => 'ACHNANTHES Bory, Dict. Class. Hist. Nat. 1: 79 (1822). / SUCINCIÄžI.',
  1 => 'A. brevipes C.Agardh, Syst. Alg.: 1 (1824). / Küçük sucıncığı.',
  2 => 'A. coarctata (Bréb. ex W.Sm.) Grunow, Syn. Diat. Belg.: expl. pl. XXVI: ş. 17 (1880). / Dar sucıncığı.',
  3 => 'A. cocconeiformis Mann, U.S. Nat. Mus., Bull. 6: 182 (1925). / Top sucıncığı.',
  4 => 'A. gibberula Grunow, Kongl. Svenska Vetensk.-Akad. Handl. 17(2): 121 (1880). / Kambur sucıncığı.',
  5 => 'A. lacunarum Hust., Bacillariophyta (Diatomeae) Zweite Auflage, Süsswass.-Fl. Mitteleurop. 10: 205 (1930). / Delikli sucıncığı.',
  6 => 'A. lineariformis Lange-Bert., Biblioth. Diatomol. 27: 7, 134 pl. (1993). / Düz sucıncığı.',
  7 => 'A. longipes C.Agardh, Syst. Alg.: 1 (1824). / Boylu sucıncığı.',
  8 => 'A. nollii Bock, Nachrichtendes Naturwiss. Museums Stadt Aschaffenburg 38: 1 (1953). / Yaban sucıncığı.',
  9 => 'A. parvula Kütz., Bacillarien: 76, pl. 21: ş. 5 (1844). / Saf sucıncığı.',
  10 => 'A. petersenii Hust., Rabenhorst’s Krypt.-Fl. Deutschl.: 179, ş 10-14 (1937). / Bal sucıncığı.',
  11 => 'A. pyrenaicum (Hust.) H.Kobayasi, Nova Hedwigia 65(1-4): 148, ş. 1-18 (1997). / Garip sucıncığı.',
  12 => 'A. stolida (Krasske) Krasske, Ann. Acad. Sc. Fenn., ser. A, Biol. 14: 78 (1949). / Alık sucıncığı.',
  13 => 'A. thermalis (Rabenh.) Schoenfeld, Diat. German.: 122 (1907). / Sıcak sucıncığı.',
  14 => 'A. trinodis (Ralfs) Grunow, Syn. Diatom. Belg.: pl. XXVII: ş. 50 (1880). / Üç sucıncığı.',
  15 => 'A. wellsiae Reimer, Monogr. Acad. Nat. Sci. Philadelphia 1: 16 (1966). / El sucıncığı.',
  16 => 'PLATESSA Lange-Bert., Süsswass.-Fl. Mitteleuropa 2: 443 (2004). / SUTANESİ.',
  17 => 'P. conspicua (Ant.Mayer) Lange-Bert., Süsswass.-Fl. Mitteleuropa 2: 445 (2004). / Küt sutanesi.',
  18 => 'P. montana (Krasske) Lange-Bert., Süsswass.-Fl. Mitteleuropa 2: 445 (2004). / Dağ sutanesi.',
  19 => 'P. salinarum (Grunow) Lange-Bert. / Sutanesi.',
  20 => 'ACHNANTHIDIUM Kütz., Bacillarien: 75 (1844). / SUÇUBUĞU.',
  21 => 'A. affine (Grunow) Czarn., Mem. Calif. Acad. Sci. 17: 156 (1994). / Hoş suçubuğu.',
  22 => 'A. deflexum Kingston, Diatom Res. 15(2): 409 (2000). / Kıvrık suçubuğu.',
  23 => 'A. exiguum (Grunow) Czarnecki, Mem. Calif. Acad. Sci. 17: 155 (1994). / Delikli suçubuğu.',
  24 => 'A. exile (Kütz.) Heiberg, Conspect. Diatom. Dan.: 119 (1863). / Bitik suçubuğu.',
  25 => 'A. lanceolatum (Bréb.) Kütz., Bot. Zeitung 4(14): 247 (1846). / Uzun suçubuğu.',
  26 => 'A. minutissimum (Kütz.) Czarn., Mem. Calif. Acad. Sci. 17: 155 (1994). / Cüce suçubuğu.',
  27 => 'A. minutum Cleve, Fl. Fenn. 8(2): 1 (1891). / Bodur suçubuğu.',
  28 => 'A. thermale Rabenh., Fl. Eur. Alg. 1: 107 (1864). / Sıcak suçubuğu.',
  29 => 'EUCOCCONEIS Cleve ex Meister, Beitr. Kryptogamenfl. Schweiz IV(1): 95 (1912). / SUESNEĞİ.',
  30 => 'E. flexella (Kütz.) Meister, Beitr. Kryptogamenfl. Schweiz IV(1): 95 (1912). / Suesneği.',
  31 => 'E. laevis (Østrup) Lange-Bert., Iconogr. Diatomol. 6: 46 (1999). / Pek suesneği.',
  32 => 'E. quadratarea (Østrup) Lange-Bert., Iconogr. Diatomol. 6: 48 (1999). / Dört suesneği.',

Je veux le transformer en ceci:

ACHNANTHES
Achantes brevipes
Achantes coarctata
Achantes cocconeiformis
Achantes gibberula
Achantes lacunarum
Achantes lineariformis
Achantes longipes
Achantes nollii
Achantes parvula
Achantes petersenii
Achantes pyrenaicum
Achantes stolida
Achantes thermalis
Achantes trinodis
Achantes wellsiae
PLATESSA
Platessa conspicua
Platessa montana
Platessa salinarum
ACHNANTHIDIUM
Achanthidium affine
Achanthidium deflexum
Achanthidium exiguum
Achanthidium exile
Achanthidium lanceolatum

Je pense que je dois utiliser while ou foreach dans PHP, mais je ne sais pas comment faire. Aide s'il vous plaît.

@mickmackmusa comme vous le vouliez voici une partie de mon tableau:

ACHNANTHES
A. brevipes
A. coarctata
A. cocconeiformis
A. gibberula
A. lacunarum 
A. lineariformis
A. longipes
A. nollii
A. parvula
A. petersenii
A. pyrenaicum
A. stolida
A. thermalis
A. trinodis
A. wellsiae
PLATESSA
P. conspicua
P. montana
P. salinarum
ACHNANTHIDIUM
A. affine
A. deflexum
A. exiguum
A. exile
A. lanceolatum
A. minutissimum
A. minutum
A. thermale


10 commentaires

Ces chaînes sont-elles des éléments de tableau individuels pour commencer? Autrement dit, avez-vous quelque chose comme $ species = ['ACHNANTHES', 'A. brevipes »,« A. coarctata ', ...];


oui, chaque ligne est un index de tableau comme [0], [1] ...


Cette liste est-elle prête à être triée? Pourquoi ne pas la stocker en tant que valeur de clé telle que [ARCHANTHES => [brevipes, ...] et lorsque vous souhaitez y accéder, strtolower la clé et obtenir la ou les valeurs suivantes


Je ne sais pas comment faire et c'est une très longue liste comme 4000 lignes


Veuillez fournir, en tant que modification de votre question, une petite représentation réaliste de vos données - dans sa forme de tableau la plus vraie. Utilisez var_export () et copiez-collez ce texte dans votre question. @Shraun


@Shraun pour vous fournir la solution la plus efficace et la plus directe, nous aurons besoin de voir comment vos données sont générées au plus tôt dans votre projet. Si cela provient d'un fichier, de quel type de fichier s'agit-il et comment les données sont-elles formatées? s'il provient d'une base de données, montrez-nous l'ensemble de résultats. S'il commence sous forme de texte, vous le divisez en éléments de tableau en explosant sur les retours à la ligne, alors il s'agit d'un travail supplémentaire inutile car il semble que vous ayez à nouveau un résultat souhaité qui est une seule chaîne de texte. Nous avons besoin de détails très clairs de votre part. Je serai heureux d'aider une fois la question réglée.


je l'ai ajouté à ma question


@Shraun Je peux travailler avec ce tableau, mais d'où vient ce tableau? et quelle sortie exacte voulez-vous? Voulez-vous conserver la structure du tableau ou générer un seul bloc de texte / chaîne qui utilisera des retours à la ligne pour séparer. Je ne veux pas perdre de temps à fournir quelque chose dont vous ne voulez pas. Je veux traiter cela à partir de sa forme la plus brute et générer la sortie EXACTE souhaitée. Comment utilisez-vous ces données après cette étape? L'afficher simplement à l'écran? Le stocker dans un fichier? Générer du contenu html avec? J'ai voté pour votre question, mais je veux toujours plus - cela en vaudrait la peine.


Je vais pousser chaque ligne comme une ligne dans la base de données sql


J'aimerais voir la déclaration préparée que vous prévoyez de mettre en œuvre. Parce que si je ne vois pas les colonnes dans lesquelles vous allez insérer des données, je pourrais finir par faire un travail inutile. Veuillez me montrer le schéma dans lequel vous allez transférer des données. Utilisez-vous pdo ou mysqli? Le site me demande de créer une salle de discussion, mais je n'ai pas le temps ni l'intérêt de le faire. Veuillez modifier votre question pour fournir tous les détails demandés.


3 Réponses :


0
votes

Je serais ravi d'avoir tort mais je ne pense pas que le résultat souhaité puisse être obtenu avec le moteur de regex PCRE, en utilisant de simples substitutions.

Supposons que la chaîne soit

^                # match beginning of line
[A-Z]\.          # match uc ltr then '.' 
(?=              # begin non-cap grp
  \s+[a-z]+\s*   # match 1+ whtspaces, 1+ lc ltrs, 0+ whtspaces
  (?:            # begin non-cap grp
    [A-Z]\.      # match line begin with uc ltr then '.'
    \s+[a-z]+\s* # match 1+ whtspaces, 1+ lc ltrs, 0+ whtspaces 
  )              # end non-cap grp
  *              # execute non-cap grp 0+ times
  ([A-Z]+)       # match 1+ uc ltrs in cap grp 1
  \s*            # match 0+ whtspaces
  $              # match end of line
)                # end positive lookahead      


3 commentaires

Je crois que je pourrais peut-être vous prouver le contraire, mais j'attendrai que l'OP mette à jour la question avec une représentation plus précise de l'entrée et de la sortie exacte souhaitée.


@mickmackusa, j'espère que vous le faites (vraiment). Votre poignée est étrange pour un Australien.


... doit être la dyslexie



0
votes

Pour résoudre votre problème, je voudrais d'abord réfléchir au type de logique que vous allez utiliser avant de penser aux spécificités du langage PHP. La plupart des langages de programmation à usage général (tels que PHP) peuvent faire presque tout ce dont vous auriez besoin en ce qui concerne la manipulation de chaînes, alors ne vous inquiétez pas de la façon dont vous allez implémenter votre logique maintenant.

Je pense que l'utilisation d'une bibliothèque regex serait être exagéré dans cette situation. Il existe de nombreuses façons de résoudre votre problème, et il y en a généralement une meilleure que ce qui me vient à l'esprit, mais je vais revenir sur la logique de ce qui m'est venu à l'esprit.

Premièrement, Je vais passer en revue certaines hypothèses importantes. Il a été implicite que les lignes de genre ne contiennent que des lettres, et les lignes d'espèces commenceront par une lettre, puis un point. Je suppose également trois nouveautés:

  1. Il n'y a pas d'autres types de lignes que les lignes de genre et les lignes d'espèces
  2. Les lignes de genre comportent au moins deux caractères
  3. La toute première ligne est un nom de genre.

Toutes ces hypothèses doivent être vraies, et si elles le sont, alors cette solution fonctionnera. Voici ma logique en anglais:

Declare a variable that will be a string that keeps track of your current genus name 

For each line (AKA for each string in your array), do this chunk of code:
  See if the second letter of the current line is not a dot
    If it is not, this line is your current genus name: change
      your current genus name variable to the current line
  BUT... if the second letter of the current line IS a dot
    This is a species line, and we will need to transform it, and to do that...
    Make a new string that is the current line with the first two characters cut off
    Make a new string copy of your current genus name, but where it just 
      starts with a capital instead of being all-caps
    Make a new string, which is those two strings you just made put together
    Replace the current line with that newest string you just made

Maintenant, je ne vais pas vous donner une solution pure et simple, car Stack Overflow me détestera si je vous prive de cette opportunité d'apprentissage , mais je vais vous expliquer une syntaxe utile pour résoudre ce problème.

boucles foreach https://www.w3schools.in/php/looping/foreach/

chaînes https://www.php.net/language.types.string (recherchez 'String access et modification par caractère ')

instructions if et else https://www.w3schools.com/php/php_if_else.asp

sous-chaîne https://www.php.net/manual/en/function.substr.php

fonctions de casse de chaîne utiles https://www.javatpoint.com / php-string-strtolower-function

concaténation de chaînes https://www.php.net/manual/en/language.operators.string.php

PS - une très bonne solution aura une gestion des erreurs, comme ce qu'il faut faire dans le cas où il y aurait un nom de genre qui ne comporte qu'un seul caractère, ou avec des lignes qui ne sont que des caractères de retour, etc., mais pour des raisons de simplicité, je ne l'ai pas faites cela dans cette solution. Cette réponse devrait convenir à vos besoins, gardez simplement à l'esprit que la gestion des erreurs est une bonne pratique et vous évitera beaucoup de maux de tête sur la route.


0 commentaires

1
votes

Je suis un peu déçu de ne pas avoir assez de détails pour vous amener jusqu'au processus de requête, donc je vais simplement muter les valeurs de vos éléments.

  1. Établissez une chaîne de regroupement - la variable Genus. Définissez-le sur null avant d'entrer dans la boucle
  2. Au fur et à mesure que vous itérez, déterminez si la ligne actuelle est une valeur de genre en extrayant le premier mot, puis en vérifiant si elle est composée exclusivement de lettres majuscules.
    • si tel est le cas, mettez-la en cache en tant que nouvelle valeur de regroupement et stockez-la dans le tableau de sortie
    • sinon, insérez la chaîne formatée "Genus species" dans le tableau des résultats

J'adore les regex, mais comme vos données sont déjà divisées en éléments, il n'y a aucun avantage à utiliser des regex pour cette tâche.

Code: ( Démo )

array (
  0 => 'ACHNANTHES',
  1 => 'Achnanthes brevipes',
  2 => 'Achnanthes coarctata',
  3 => 'Achnanthes cocconeiformis',
  4 => 'Achnanthes gibberula',
  5 => 'Achnanthes lacunarum',
  6 => 'Achnanthes lineariformis',
  7 => 'Achnanthes longipes',
  8 => 'Achnanthes nollii',
  9 => 'Achnanthes parvula',
  10 => 'Achnanthes petersenii',
  11 => 'Achnanthes pyrenaicum',
  12 => 'Achnanthes stolida',
  13 => 'Achnanthes thermalis',
  14 => 'Achnanthes trinodis',
  15 => 'Achnanthes wellsiae',
  16 => 'PLATESSA',
  17 => 'Platessa conspicua',
  18 => 'Platessa montana',
  19 => 'Platessa salinarum',
  20 => 'ACHNANTHIDIUM',
  21 => 'Achnanthidium affine',
  22 => 'Achnanthidium deflexum',
  23 => 'Achnanthidium exiguum',
  24 => 'Achnanthidium exile',
  25 => 'Achnanthidium lanceolatum',
  26 => 'Achnanthidium minutissimum',
  27 => 'Achnanthidium minutum',
  28 => 'Achnanthidium thermale',
  29 => 'EUCOCCONEIS',
  30 => 'Eucocconeis flexella',
  31 => 'Eucocconeis laevis',
  32 => 'Eucocconeis quadratarea',
)

Sortie:

$result = [];
$currentGenus = null;
foreach ($array as $line) {
    $firstWord = strstr($line, ' ', true);
    if (ctype_upper($firstWord)) {
        $currentGenus = $firstWord;
        $result[] = $firstWord;
    } else {
        $result[] = ucfirst(strtolower($currentGenus)) . ' ' . explode(' ', $line, 3)[1];
    }
}
var_export($result);


0 commentaires