Autor | Zpráva | ||
---|---|---|---|
__martin Profil * |
Ahoj,
dělám aplikaci v C#. Načítám textový soubor. Celkem 35 000 řádků. V každém řádku 6 - 8 sloupců. Načtu textový soubor do proměnné a zpracovávám pomocí regulárního výrazu. Řekněme, že ve 3. a 4. sloupci je se vyskytuje 23 tísíc krát řetězec "2000 2000". Já toto číslo potřebuji nahradit za 2000 + číslo výskytu. Výsledek by byl tedy: "20000001 20000001", "20000002 20000002"... Naprogramovat jsem to dokázal (kód níže), problém je, že celé nahrazení trvá 18 minut, což nený zrovna málo. Soubor má 2,5MB a já bych rád zpracoval třeba i soubory větší (40MB). String result = NACTENY SOUBOR; // pole cisla obsahuje cisla (cca 40), ktera je nutna nahradit, v nasem pripade 2000, ale i dalsi for (int x = 0; x < cisla.Count; x++) { String pattern = "(" + cisla[x] + ")(\\s+)(" + cisla[x] + ")"; Regex reg_replace = new Regex(pattern); int pocet = reg_replace.Matches(result).Count; // pocet výskytů konkrétního čísla int cislo = 1; String replacement = ""; // pokud první číslo (např. 2000) je obsaženo 23 tisíc krát, tak tolikrát se tento cyklus provede for (int i = 0; i <= pocet; i++) { replacement = "${1}" + cislo.ToString("0000") + "${2}${3}" + cislo.ToString("0000"); result = reg_replace.Replace(result, replacement, 1, i); cislo++; } } Já jsem se chtěl zeptat, jestli není možné se zbavit vloženého cyklu, aby se neprováděl tolikrát. Možná existuje nějaký interní čítač, ze kterého by se dalo jednoduše dostat pořadí konkrétního výskytu. Takže řádek replacement = "${1}" + cislo.ToString("0000") + "${2}${3}" + cislo.ToString("0000"); by mohl vypadat takto replacement = "${1}" + INTERNI_KONSTANTA.ToString("0000") + "${2}${3}" + INTERNI_KONSTANTA.ToString("0000"); a ja bych mohl vypustit cyklus. Dá se tomu rozumět? Nějaké další návrhy na zrychlení? Děkuji. |
||
Chamurappi Profil |
#2 · Zasláno: 14. 7. 2010, 20:52:06
Reaguji na __martina:
\\1 |
||
__martin Profil * |
#3 · Zasláno: 14. 7. 2010, 21:30:40
Chamurappi:
Díky moc, nevím, jestli jsem to dobře pochopil. Vyplývá z toho, že "INTERNI_KONSTANTA" můžu nahradit za \\1? Tedy že celý cyklus kódem: replacement = "${1}\\1${2}${3}\\1"; result = reg_replace.Replace(result, replacement); Jak se \\1 říká? Rád bych si to vygooglil. Protože po spuštění kódu výše se \\1 nahradí jen za \1. Díky |
||
Chamurappi Profil |
#4 · Zasláno: 14. 7. 2010, 21:50:37
Reaguji na __martina:
Aha, pardon, dotaz jsem prohlédl jen zběžně a odpověděl na něco jiného. Druhým argumentem funkce Regex.Replace může být delegát MatchEvaluator, tedy v podstatě funkce — v ní si můžeš inkrementovat proměnnou a náhradou bude řetězec, který tato funkce vrací. Na příklad použití s anonymním delegátem se mrkni třeba sem.
|
||
_es Profil |
#5 · Zasláno: 14. 7. 2010, 22:38:50
__martin:
„problém je, že celé nahrazení trvá 18 minut“ Asi by sa to veľmi zrýchlilo úplným odstránením regulárnych výrazov a nahradením ich funkčnosti vhodným použitím iných metód pre textové reťazce. |
||
__martin Profil * |
#6 · Zasláno: 14. 7. 2010, 22:39:40
Díky moc! Zrychlení na 15 vteřin!
for (int x = 0; x < cisla.Count; x++) { String pattern = "(?<param1>" + cisla[x] + ")(?<param2>\\s+)(?<param3>" + cisla[x] + ")"; Regex reg_replace = new Regex(pattern); int pocet = reg_replace.Matches(result).Count; result = reg_replace.Replace(result, this.Regular); citac = 0; } public static int citac = 0; public string Regular(Match m) // Replace each Regex cc match with the number of the occurrence. { citac++; return m.Groups["param1"].Value + citac.ToString("0000") + m.Groups["param2"].Value + m.Groups["param3"].Value + citac.ToString("0000"); } jsou to dva vytržené kusy kódu, ale snad někomu pro ilustraci pochopí. Díky! |
||
Časová prodleva: 14 let
|
0