Vytvoření stringu z kolekce znaků

Ondřej Janáček       27. 7. 2014       C#, Optimalizace, .NET       4593 zobrazení

Jaké máme možnosti? Která je nejlepší? Tyto dvě otázky jsem si nedávno položil ve chvíli, kdy jsem potřeboval napsat metodu pro výběr části textu, jejíž funkcionalita přesahuje možnosti metody text.Substring().

 

Mým záměrem bylo vzít prvních 200 smysluplných znaků z přijatého textu a vrátit je v podobě nového textu. Za smysluplné v tomto případě považuji všechny znaky z ASCII tabulky s hodnotou vyšší než 31. Protože i tohle je dotaz nad kolekcí dat, LINQ byla jasná volba.

static string Shorten(string text)
{
    if (string.IsNullOrWhiteSpace(text)) return "";

    var chars = text.Where(c => c > 31).Take(200);
    return ???
}

Zaseknul jsem se ale u příkazu return. Nebylo to vyloženě, že bych nevěděl, jak dál, ale co zvolit? Na výběr je tu rovnou ze tří možností, které mě napadají.

  1. Jeden z konstruktorů třídy String přijímá jako parametr pole znaků – String(Char[]).
  2. Jedno z přetížení metody string.Concat() přijímá jako parametr sekvenci objektů libovolného typu – string.Concat<T>(IEnumerable<T>).
  3. Použít třídu StringBuilder.

V prvním případě by bylo nutné nejdříve sekvenci znaků převést na pole zavoláním chars.ToArray(). To na první pohled nevypadá příliš efektivně, nejdříve převést sekvenci na pole a poté to předat konstruktoru, který s ním provede svoje. Concat interně používá StringBuilder, ale předtím než každý prvek sekvence připojí, převede jej na string. Přímé použití StringBuilderu tedy zní jako nejlepší nápad. Bylo mi jasné, že nejsem první, kdo tento problém řeší a tak jsem hledal a našel otázku s řešením na stackoverflow, kde se moje teorie potvrdila testy. Nicméně, překvapilo mě, že první varianta zaostává za třetí jen nepatrně, a že Concat() je víc než 2x pomalejší oproti zbytku. Při řídkém použití by bylo úplně jedno, kterou z variant použijete, ale pokud se taková metoda nachází na tzv. “hotpath”, tedy je volána tak často, že její výkon ovlivňuje výkon celé aplikace, pak je dobré se na ni podívat opravdu zblízka.

Používám tedy pro snadnou čitelnost

static string Shorten(string text)
{
    if (string.IsNullOrWhiteSpace(text)) return "";

    var chars = text.Where(c => c > 31).Take(200);
    return new string(chars.ToArray());
}

i když

static string Shorten(string text)
{
    if (string.IsNullOrWhiteSpace(text)) return "";

    var chars = text.Where(c => c > 31).Take(200);
    var sb = new StringBuilder();
    foreach (var c in chars)
    {
        sb.Append(c);
    }
    return sb.ToString();
}

je výkonnější. Je nutno poznamenat, že výše uvedené testy byly provedeny v izolovaném prostředí a je možné, že na jiných strojích v jiném prostředí se budou lišit. Nicméně na začátek to stačí. Kdybych viděl, že aplikace nestíhá, provedl bych vlastní měření a zařídil se podle toho. Nemá ale cenu optimalizovat předčasně. V některém z příštích článků se přímo k této metodě ještě vrátím a podíváme se na ni z trochu jiného pohledu.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback