Meest efficiënte manier om het eerste teken in tekenreeks te bepalen?

Welke van deze methoden is de meest efficiënte of is er een betere manier om dit te doen?

this.returnList[i].Title[0].ToString()

of

this.returnList[i].Title.Substring(0, 1)
2
Maakt het uit? Heb je prestatieproblemen? Wat zei je benchmark?
toegevoegd de auteur Oded, de bron
SubString() voert een reeks bereikcontrole uit, dus het is een beetje langzamer.
toegevoegd de auteur Igby Largeman, de bron
Het soort dingen dat je zal helpen om betere code te schrijven, is meten hoe lang het duurde om de code te schrijven, testen en uitvoeren.
toegevoegd de auteur Dour High Arch, de bron
En als je nieuwsgierig bent, wat eerlijk is, is het eenvoudig te meten.
toegevoegd de auteur codekaizen, de bron
@slinzerthegod - hier is een eenvoudige test om vanaf te starten: pastebin.com/aUUGhJ7g Vergeet niet om het meerdere keren uit te voeren, ook je moet het aanpassen zodat de volgorde van de testen anders is, anders zal dit de resultaten beïnvloeden.
toegevoegd de auteur codekaizen, de bron
Ik zou degene gebruiken die het meest logisch voor je is als je je code terugleest.
toegevoegd de auteur hspain, de bron
@Oded Ik ben nog steeds heel vroeg in mijn C# -carrière, om te weten dat dit soort dingen me misschien zullen helpen om in de toekomst betere code te schrijven.
toegevoegd de auteur slinzerthegod, de bron
@codekaizen Dank u, ik zal daarnaar kijken.
toegevoegd de auteur slinzerthegod, de bron

5 antwoord

Ze zijn allebei erg snel:

Char Index

var sample = "sample";
var clock = new Stopwatch();
for (var i = 0; i < 10; i++)
{
    clock.Start();
    for (var j = 0; j < 10000000; j++)
    {
        var first = sample[0].ToString();
    }
    clock.Stop();
    Console.Write(clock.Elapsed);
    clock.Reset();
}

// Results
00:00:00.2012243
00:00:00.2207168
00:00:00.2184807
00:00:00.2258847
00:00:00.2296456
00:00:00.2261465
00:00:00.2120131
00:00:00.2221702
00:00:00.2346083
00:00:00.2330840

Substring

var sample = "sample";
var clock = new Stopwatch();
for (var i = 0; i < 10; i++)
{
    clock.Start();
    for (var j = 0; j < 10000000; j++)
    {
        var first = sample.Substring(0, 1);
    }
    clock.Stop();
    Console.Write(clock.Elapsed);
    clock.Reset();
}

// Results
00:00:00.3268155
00:00:00.3337077
00:00:00.3439908
00:00:00.3273090
00:00:00.3380794
00:00:00.3400650
00:00:00.3280275
00:00:00.3333719
00:00:00.3295982
00:00:00.3368425

Ik ben het ook eens met BrokenGlass dat het gebruik van de char-index een schonere manier is om het te schrijven. En als je het 10 biljoen keer doet, zal het veel sneller zijn!

3
toegevoegd
@slinzerthegod Geen probleem. Download LINQPad linqpad.net Het is gratis en absoluut onmisbaar. Hiermee kunt u snel en eenvoudig C# -code spelen en testen. Zorg er ook voor dat u een antwoord aanvinkt als geaccepteerd als het uw vraag naar tevredenheid heeft beantwoord.
toegevoegd de auteur Lucifer Sam, de bron
Bedankt voor het op een duidelijke manier illustreren van het verschil!
toegevoegd de auteur slinzerthegod, de bron

Er is een grote maas in uw code die problemen kan veroorzaken, afhankelijk van wat u bedoelt met "eerste teken" en wat returnList bevat.

C # strings bevatten UTF-16, wat een variabele lengte codering is en als returnList een array van strings is, dan kan returnList [i] slechts één zijn char van een Unicode-punt. Als u het eerste Unicode-diagram van een tekenreeks wilt retourneren:

string s = returnList[i].Title;
if (string.IsNullOrEmpty(s))
    return s;

int charsInGlyph = char.IsSurrogatePair(s, 0) ? 2 : 1;
return s.Substring(0, charsInGlyph);

U kunt dezelfde problemen tegenkomen met stuklijsten, getagd en tekens combineren; dit zijn allemaal geldige tekens, maar zijn niet zinvol als ze worden weergegeven aan een gebruiker.

Als u Unicode-punten of -grafieken, geen tekens, wilt, moet u strings gebruiken; Unicode-diagrammen kunnen meer dan één tekenreeks zijn.

2
toegevoegd

Ik denk niet dat het efficiënt genoeg zou zijn, maar naar mijn mening is de duidelijkere, meer idiomatische en dus beter onderhoudbare manier om het eerste personage terug te sturen, de index-operator:

char c = returnList[i].Title[0];

Dit veronderstelt natuurlijk dat er ten minste één karakter is, als dat geen gegeven is, moet je dat controleren.

1
toegevoegd

Die zouden qua prestaties bijna identiek moeten zijn.

Het dure deel van de operatie is om de string te maken, en er is geen efficiëntere manier om dat te doen.

Tenzij je wilt voorafgaan aan het maken van strings voor alle mogelijke personages en op te slaan in een woordenboek, maar dat zou veel geheugen gebruiken voor zo'n triviale taak.

0
toegevoegd

returnList[I].Title[0] is much faster as it does not need to create a new string, only accessing a char from the original one. Of course, it will throw an exception if the string is empty, so you should check that first.

Als vuistregel, gebruik nooit strings met een vaste lengte van 1. dat is waarvoor char is.

Het prestatieverschil zal waarschijnlijk niet van belang zijn, maar de betere leesbaarheid zal dat zeker wel doen.

0
toegevoegd
@Charles, waarom niet gewoon vergelijken met karakters? returnList [I] .Title [0] = 'A'c
toegevoegd de auteur Hand-E-Food, de bron
@Charles: Waarom zou je de char terug willen converteren naar een string? het doorgeven van 1-snarige lengtes van vaste lengte is niet logisch ...
toegevoegd de auteur Falanwe, de bron
Eigenlijk moet je nog steeds een nieuwe string maken, wanneer je de char naar een string converteert. ( char.ToString() )
toegevoegd de auteur Igby Largeman, de bron
Kijk naar de code die de OP heeft gepost. De vraag specificeert het doen van ToString() op de char.
toegevoegd de auteur Igby Largeman, de bron