Есть ли способ преобразовать строку в соответствии с текстовой строкой выше? - PullRequest
1 голос
/ 03 апреля 2020

У меня есть длинный список массивов, который включает строки рода (начинаются с заглавных букв, таких как: ACHNANTHES) и строки видов (начинаются с заглавной буквы и начинаются с точки, например: A.) Мне нужно преобразовать небольшую часть, как указано выше текст. Ниже вы можете легко понять:

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

Я хочу преобразовать это в это:

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

Думаю, мне нужно использовать while или foreach в PHP, но я не не знаю, как это сделать. Помогите пожалуйста.

@ mickmackmusa, как вы и хотели, является частью моего массива:

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.',

Ответы [ 3 ]

1 голос
/ 03 апреля 2020

Я немного разочарован тем, что у меня недостаточно подробностей, чтобы вы могли пройти весь процесс запроса, поэтому я просто изменю значения вашего элемента.

  1. Establi sh Строка группировки - переменная Genus. Установите нулевое значение перед вводом l oop
  2. . При выполнении итерации определите, является ли текущая строка значением рода, извлекая первое слово, а затем проверяя, состоит ли оно исключительно из заглавных букв.
    • если это так, кэшируйте его как новое значение группировки и сохраните его в выходном массиве
    • , если нет, то pu sh отформатированную строку «Род видов» в массив результатов

Я люблю регулярные выражения, но поскольку ваши данные уже разбиты на элементы, использование регулярных выражений для этой задачи бесполезно.

Код: ( Демо )

$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);

Выход:

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',
)
0 голосов
/ 03 апреля 2020

Чтобы решить вашу проблему, я сначала подумал бы, какой тип логики c вы собираетесь использовать, прежде чем думать о какой-либо специфике языка PHP. Большинство языков программирования общего назначения (например, PHP) могут делать практически все, что вам нужно в отношении работы со строками, поэтому не беспокойтесь о том, как вы собираетесь реализовать свою логику c прямо сейчас.

Я думаю, что использование библиотеки регулярных выражений было бы излишним в этой ситуации. Есть много способов решить вашу проблему, и обычно есть лучший, чем первый, который приходит мне в голову, но я буду go по логике c того, что сначала пришло мне в голову.

Во-первых, я собираюсь go из-за некоторых важных предположений. Подразумевалось, что строки рода содержат только буквы, а строки видов будут начинаться с буквы, а затем с точки. Я также предполагаю три новые вещи:

  1. Нет других типов строк, кроме строк рода и строк вида
  2. Строки рода имеют длину не менее двух символов
  3. Самая первая строка - это название рода.

Все эти предположения должны быть верными, и если они верны, то это решение будет работать. Вот моя логика c на английском языке sh:

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

Теперь я не собираюсь давать вам прямое решение, потому что переполнение стека возненавидит меня, если я лишу вас этой возможности обучения , но я дам вам некоторый полезный синтаксис о том, как решить эту проблему.

циклы foreach https://www.w3schools.in/php/looping/foreach/

строки https://www.php.net/language.types.string (поиск 'Доступ к строке и ее модификация по символу')

операторы if и else https://www.w3schools.com/php/php_if_else.asp

подстрока https://www.php.net/manual/en/function.substr.php

полезные строковые функции https://www.javatpoint.com/php-string-strtolower-function

конкатенация строк https://www.php.net/manual/en/language.operators.string.php

PS - действительно хорошее решение будет иметь обработку ошибок, например, что делать в случае, если имя рода длина всего одного символа или строки, которые являются только возвращаемыми символами и т. д. c, но для простоты я не делал этого в этом решении. Этот ответ должен работать для ваших целей, просто имейте в виду, что обработка ошибок - это хорошая практика и избавит вас от головной боли в будущем.

0 голосов
/ 03 апреля 2020

Я был бы рад оказаться неправым, но я не думаю, что желаемый результат можно получить с помощью механизма регулярных выражений PCRE, используя простые замены.

Предположим, что строка была

ACHNANTHES
A. brevipes
A. coarctata
A. cocconeiformis
PLATESSA
P. conspicua
P. montana
P. salinarum

Если вы перевернули строки, чтобы получить

P. salinarum
P. montana
P. conspicua
PLATESSA
A. cocconeiformis
A. coarctata
A. brevipes
ACHNANTHES

, вы можете использовать регулярное выражение

^[A-Z]\.(?=\s+[a-z]+\s*(?:[A-Z]\.\s+[a-z]+\s*)*([A-Z]+)\s*$)

, чтобы получить совпадения и заменить каждое на содержимое группы захвата, чтобы получить

PLATESSA salinarum
PLATESSA montana
PLATESSA conspicua
PLATESSA
ACHNANTHES cocconeiformis
ACHNANTHES coarctata
ACHNANTHES brevipes
ACHNANTHES

, в этот момент желаемый результат получается путем обращения этих строк:

ACHNANTHES
ACHNANTHES brevipes
ACHNANTHES coarctata
ACHNANTHES cocconeiformis
PLATESSA
PLATESSA conspicua
PLATESSA montana
PLATESSA salinarum

Демонстрация

Следующие операции выполняются PHP regex engine, PCRE.

^                # 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      
...