7. 1. 2014, Vladimír Klaus, přečteno 3658x
Dříve nebo později vás v C# překvapí, jak poněkud hloupě pracuje funkce Substring(). Když totiž zadáte požadovanou délku, která přesahuje délku vlastního textu, skončí to výjimkou.
Takto vypadá problematický příklad:
var Text = "Malý text"; var KratsiText = Text.Substring(0, 10);
Řešení je jednoduché – napíšeme si bezpečnější funkci, která délku ohlídá.
//Bezpečnější varianta, která neskončí výjimkou, pokud je textový //řetězec kratší než požadovaná délka public static string LeftStr1(string s, int length) { return (s.Length > length) ? s.Substring(0, length) : s; }
Docela často ale potřebujete textový řetězec nejen zkrátit, ale také nějak ukázat, že došlo ke zkrácení. Nejčastěji se přidávají tři tečky, proto si funkci trochu vylepšíme. A to také tím, aby zkrácený text nekončil uprostřed slova.
//Druhá varianta umožní doplnit v případě zkrácení třeba ještě tečky public static string LeftStr2(string s, int length, string ending = "") { int lastDelim; //pokud bude třeba text zkracovat if(s.Length > length) { //nejprve zkrátím text na zadanou délku, dále budu hledat //oddělovač a zkracovat lépe s = s.Substring(0, length); //najdeme poslední mezeru lastDelim = s.LastIndexOf(" "); //pokud tam nějaká je, zkrátím to k ní if(lastDelim > 0) { s = s.Substring(0, lastDelim); } //pokud chci nějaké zakončení, tak ho přidám if(ending != "") { s += ending; } } return s; }
Určitě vás napadá další vylepšení této funkce – třeba moci zadat místo pouhé mezery celou sadu oddělovačů. To se může hodit, pokud jsou v textu pevné mezery, tabelátory apod. Zároveň by bylo ale potřeba, aby se sada oddělovačů nemusela zadávat, stejně tak jako zakončovací řetězec v předchozí variantě.
//Třetí varianta vychází z druhé, pouze umožňuje zadat sadu oddělovačů, //které se budou hledat. To se může hodit, pokud jsou v textu pevné //mezery, tabelátory apod. public static string LeftStr3(string s, int length, string[] delims = null, string ending = "") { int lastDelim; //pokud bude třeba text zkracovat if(s.Length > length) { //nejprve zkrátím text na zadanou délku, dále budu hledat oddělovač //a zkracovat lépe s = s.Substring(0, length); //pokud nezadám sadu oddělovačů, vytvořím si vlastní sadu o jednom //prvku, který bude obsahovat mezeru if(delims == null) { delims = new string[] {" "}; } //nyní najdu oddělovač, který je nejblíže konci lastDelim = -1; foreach (string delim in delims) { var pos = s.LastIndexOf(delim); if(pos>lastDelim) { lastDelim = pos; } } //pokud tam nějaký oddělovač je, řetězec zkrátím if(lastDelim > 0) { s = s.Substring(0, lastDelim); } //pokud chci nějaké zakončení, tak ho přidám if(ending != "") { s += ending; } } return s; }
Funkce potom můžete volat třeba takto:
var Text = "Malý text"; //var KratsiText = Text.Substring(0, 10); var DivnyText = "abcdefghijklmnopqrstuvwxyz"; var SlozitejsiText = "Toto je delší, pokusný text."; LeftStr1(Text, 6) LeftStr2(Text, 6) LeftStr2(Text, 6, "...") LeftStr2(DivnyText, 6, "...") LeftStr2(SlozitejsiText, 16, "...") LeftStr3(Text, 6) LeftStr3(Text, 6) LeftStr3(DivnyText, 6) //tady založíme pole, které bude obsahovat mezeru, čárku a tabelátor LeftStr3(SlozitejsiText, 16, new string[] {" ", ",", Convert.ToChar(9).ToString()}, "...")
Asi jste si všimli, že toto chytřejší řešení má oproti originální funkci jednu nevýhodu - neumí vracet část řetězce zprostředka. Ale to se při zkracování zase tak často nepoužívá a jistě si to případně budete umět doprogramovat již sami.
Tweet