Czy umieszczanie znaczników tekstowych wewnątrz ciągów jest złym stylem? Czy jest alternatywa?

10

Pracuję z ogromnymi strunami, które wymagają dużo manipulacji.

Na przykład mogę wygenerować taki ciąg:

Część 1
Łódź

Sekcja A
Programowanie

Część 2
Partycjonowanie łodzi do programowania.

Sekcja AA
Sekcja Wpisy SQL.

Ciąg byłby zbyt duży, aby ręcznie sprawdzić każdą jego część. Teraz muszę splitto stringpodzielić na stringlistsekcje i części. Mogę wymyślić dwie opcje:

Wyrażenie regularne:

QStringList sl = s.split(QRegularExpression("\n(?=Part [0-9]+|Section [A-Z]+)"));

Wygląda na to, że powinno działać, ale czasami zdarzają się wyjątki (IE: Section SQL Entriesbłędnie się podzieli)

W przeciwnym razie mogłem umieścić znacznik podczas generowania ciągu początkowego:

🚤💻 Część 1
łódź

🚤💻Sekcja
Programowanie

🚤💻 Część 2
Partycjonowanie łodzi do programowania.

🚤💻
Sekcja AA Wpisy SQL sekcji.

Co oznacza, że ​​podział łańcucha stanie się łatwy:

QStringList sl = s.split("🚤💻"));

Coś mi jednak mówi, że żadne z nich nie jest dobrym stylem ani praktyką programowania, ale do tej pory nie dyskutowałem o tym ani nie znalazłem alternatywy.

  • Gdybyś był moim kierownikiem projektu, czy zaakceptowałbyś którąś z tych metod?
  • Jeśli nie, co sugerujesz, żebym zrobił jako najlepszą praktykę?
Akiva
źródło
6
Jeśli twój program wie, gdzie umieścić te znaczniki, dlaczego nie wygenerować sekcji jako oddzielnych ciągów na początek?
Jacob Raihle
Nie sądzę, aby użytkownik korzystający z markera, który nie tłumaczy się dobrze na twoje obecne kodowanie, był dobrym pomysłem.
Tulains Córdova
2
rzeczywiste użyte symbole są w dużej mierze nieistotne, to, co zrobi różnicę, to gramatyka rzeczy, którą próbujesz przeanalizować
jk.
4
@Akiva czy jesteś pewien wydajności? W każdym razie pracujesz z taką samą ilością danych, wątpię, by była znacząca różnica. Skomponuj tysiące funkcji w jedną funkcję, wywołaj ją w pętli i dokonaj pewnych pomiarów.
Jacob Raihle
2
@Akiva Pobieranie i zastępowanie elementów na liście w najgorszym wypadku powinno być porównywalne z dzieleniem dużego ciągu.
Jacob Raihle

Odpowiedzi:

17

Kodowanie dokumentów osadzonych jako tekst w ciągu nie jest złą praktyką. Pomyśl o przecenach, HTML, XML, JSON, YAML, LaTeX itp.

Złą praktyką jest odkrywanie koła na nowo. Zamiast pisać własny procesor tekstu, zastanów się nad użyciem istniejącego standardu. Jest mnóstwo darmowego oprogramowania, które wykonuje wiele analiz dla Ciebie, a wiele z nich ma nieograniczoną licencję, która pozwala ci używać tego oprogramowania we własnym oprogramowaniu.

David Hammen
źródło
W moim przypadku wymyślam koło, jeśli staram się zbudować unikalny tłumacz dla języka przeceny. Na przykład jeden z moich projektów było interpretowanie Latex jak SSML, który jest czytelny dla ucha ludzkiego: meta.wikimedia.org/wiki/Grants:IdeaLab/... . << Na końcu tego adresu URL jest kropka, w przeciwnym razie nie zadziała
Akiva,
2
@Akiva Muszę pracować z niestandardowym formatem tekstowym opracowanym przez moje miejsce pracy, który dosłownie zmienia sposób pracy koła. Muszę dla tego prowadzić 4 parsery w 3 językach (JavaScript, Java i Objective-C), co jest koszmarnym koszmarem . Zrób teraz właściwą rzecz i zlikwiduj ten nonsens formatu niestandardowego tekstu . Nie mogę wystarczająco podkreślić, jak wielki koszmar z konserwacji stanie się kilka lat później. Użyj istniejących formatów strukturalnych, XML, JSON itp.
Chris Cirefice
@ChrisCirefice Czy możesz mi podać przykład koszmaru?
Akiva
1
@Akiva Myślę, że fakt, że musisz utrzymywać nawet jeden parser (w moim przypadku kilka i w różnych językach) jest okropny. Standardowe formaty istnieją z jakiegoś powodu - mogą reprezentować dane, których potrzebujesz - i przy bardzo małym wysiłku z twojej strony, ponieważ te parsery zostały zbudowane, dopracowane i utrzymane. Niestandardowy format tekstowy jest również niezwykle specjalistyczną wiedzą, co oznacza, że ​​zwykle tylko jeden lub dwóch programistów będzie na tyle zaznajomionych z formatem, aby z powodzeniem go obsługiwać. To powinno mówić głośno. Większość ludzi zna CML, JSON - niewielu zna niestandardowe formaty.
Chris Cirefice
1
@Akiva Rzeczywiście! Format Markdown (używany przez SE i wiele innych stron do formatowania tekstu) jest nieco standardowy , podobnie jak SQL. Ale istnieje wiele różnych „smaków” z niestandardowymi rozszerzeniami (np. SE). Istnieje standardowa biblioteka, która analizuje „rdzeń”, a następnie rozszerzasz bibliotekę, jeśli chcesz dodatkowych funkcji. Ale budowanie i utrzymywanie własnego formatyzatora byłoby absurdalne - kilka już istnieje (Markdown, kod BB itp.), Więc po co wymyślać koło i utrzymywać cały ten kod?
Również może
8

Użycie jakiegoś wspólnego separatora powinno działać dobrze podczas dzielenia większych dowolnych ciągów, ale odradzam używanie dowolnego symbolu. Ktoś czytający ten ciąg jako zwykły tekst mógłby zostać pomylony, nie wspominając o problemach z UTF i tym, czy symbol pojawia się wewnątrz sekcji, czy nie.

Najważniejszą częścią tego jest to, że każda sekcja pozostaje nienaruszona, a każdy „nagłówek sekcji” musi być odpowiednio zidentyfikowany.

Dlaczego nie zastosować wspólnego separatora, ale zachować jego czytelność? Coś jak:

[SECTION]
Part 1
Boat

[SECTION]
Section A
Programming

[SECTION]
Part 2
Partitioning boats for programming.

[SECTION]
Section AA
Section SQL Entries.

Problemem jest decyzja, jaki powinien być separator , ponieważ musi to być coś, co gwarantuje, że nie pokaże żadnej sekcji. Możesz dodatkowo zidentyfikować go jako separator , wymagając, aby znajdował się on na początku linii i jedynym tekstem w tej linii .

Bez dalszej wiedzy o tym, jakiego tekstu oczekuje się w każdej sekcji, trudno jest zalecić, który wspólny separator byłby najlepszy w tym przypadku.

Erdrik Ironrose
źródło
Podoba mi się nacisk twojej odpowiedzi na czytelność. Ciągi są generowane przez skrobanie danych tekst generowany przez użytkownika, powiedzmy na przykład język znaczników używany w SE do pisania pytań i odpowiedzi. W ten sposób możesz łatwo wyobrazić sobie, jakie rodzaje problemów z manipulowaniem strunami mogą się pojawić.
Akiva,
5

Wydaje się, że w zaakceptowanej odpowiedzi pominięto to, co napisałeś w komentarzu:

Powodem jest to, że wiele manipulacji, które wykonuję, wymaga pełnego ciągu

i podał to jako przykład:

s.replace („łódź”, „programowanie”);

Jeśli tego właśnie chcesz, IMHO jest naprawdę złym pomysłem, aby użyć „znacznika” lub separatora tekstowego dla całego łańcucha, zawsze wiąże się to z pewnym ryzykiem zakłócenia manipulacji i nie doprowadzi do powstania solidnego kodu. Zwłaszcza, gdy próbujesz zacząć używać wyrażeń regularnych na tak połączonym łańcuchu, prawdopodobnie napotkasz te same problemy, które ludzie zauważyli podczas próby przetworzenia HTLM lub XML z wyrażeniami regularnymi .

Zwłaszcza, że napisałeś, że mogą istnieć „tysiące funkcji [takich manipulacji]”, ryzyko to może stać się prawdziwym problemem. Nawet jeśli korzystasz z niektórych znaczników, takich jak XML, do wewnętrznego przechowywania listy ciągów, musisz upewnić się, że manipulacja przetworzy tylko treść, a nie przecenę, więc oznaczałoby to podzielenie łańcucha na części przed wykonaniem jakiegokolwiek przetwarzania i dołączenie potem znowu - tak, że będzie to miało wysokie ryzyko, że zapewni ci słabą wydajność.

Lepszą alternatywą projektową jest tutaj zapewnienie abstrakcyjnego typu danych (użyj klasy, jeśli chcesz), wywołanie go MyStringListi zapewnienie niewielkiego zestawu podstawowych operacji, które pozwalają zaimplementować „tysiące funkcji” pod względem tych operacji. Na przykład mogą istnieć operacje ogólne findi replaceoperacje lub ogólne mapoperacje funkcjonalne . Możesz także dodać coś takiego jak JoinToStringoperację, jeśli naprawdę potrzebujesz całej listy w jednym ciągu dla niektórych purporów.

Dzięki tym operacjom obawa, że ​​kod stanie się bardziej skomplikowany, ponieważ „wszystko musiałoby być zrobione w pętli for”, staje się bezcelowa, ponieważ jedyne dostępne forpętle są zawarte w operacjach typu danych. I nie martwiłbym się wydajnością, dopóki nie wywrzesz rzeczywistego, mierzalnego wpływu na wydajność (co wątpię, jeśli uzyskasz, jeśli poprawnie zaimplementujesz podstawowe operacje).

Doktor Brown
źródło
Głosujcie, bo tak naprawdę stworzyłem coś takiego. Pozwala mi ustawić niestandardowe nawiasy klamrowe <i >, i pobierze każdą instancję tego ciągu, w której mogę łatwo usunąć instancje, których nie chcę, i czysto manipulować nim tak, jak chcę. Jest to dobre, ponieważ same wyrażenia regularne nie obsługują takich podciągów: <boat <programming>>dobrze tam, gdzie jest wiele warstw nawiasów.
Akiva
1

Opisany format jest bardzo podobny do plików INI:

https://en.wikipedia.org/wiki/INI_file

W takim przypadku sekcja jest otoczona nawiasami kwadratowymi [], więc to, co opisujesz, ma sens, zaznaczając sekcję w jakiś sposób, aby dodać dodatkowe znaczenie do tego tekstu.

Jon Raynor
źródło
0

Na przykład mogę wygenerować taki ciąg:

Pytanie: Z czego „generujesz” ten ciąg?

Czy to będzie łatwiej manipulować?

Phill W.
źródło
Ciąg jest generowany z zawartości użytkownika Datascraping ze strony internetowej.
Akiva,
1
To nie jest niezawodny sposób na wyszukiwanie danych ze strony internetowej, po prostu dlatego, że się zmieniają i rzeczy są przenoszone lub całkowicie znikają. O wiele lepiej byłoby pobrać dane z jakiegoś opublikowanego (a zatem niezawodnego) API. Ponadto korzystanie z wielu komercyjnych stron internetowych wyraźnie zakazuje tego rodzaju rzeczy.
Phill W.,
Czasami nie mogę wybrać, które dane są dla mnie cenne, dlatego zawsze istnieje potrzeba sprawdzania integralności tego, na co patrzysz, lub po prostu zwykłego kompromisu i nadziei na najlepsze. Na przykład: napisałem LaTeXdo SSMLtłumacza, a jednym z problemów jest to, że możesz generować identyczne obrazy z zupełnie innym kodem, a więc jest prawie niemożliwe, aby być spójnym, jeśli użytkownik wybierze słabe lub ezoteryczne sposoby generowania swoich formuł. Wszystko to oznacza na koniec, że ludzie, którzy nie stosują dobrych praktyk, nie będą mieli przyzwoitej interpretacji swoich skryptów.
Akiva,