Jaki jest najbardziej efektywny sposób pisania starej szkoły:
StringBuilder sb = new StringBuilder();
if (strings.Count > 0)
{
foreach (string s in strings)
{
sb.Append(s + ", ");
}
sb.Remove(sb.Length - 2, 2);
}
return sb.ToString();
... w LINQ?
c#
linq
string-concatenation
tags2k
źródło
źródło
Odpowiedzi:
Ta odpowiedź pokazuje użycie LINQ (
Aggregate
) zgodnie z żądaniem w pytaniu i nie jest przeznaczona do codziennego użytku. Ponieważ to nie używaStringBuilder
, będzie miało straszną wydajność w przypadku bardzo długich sekwencji. Do zwykłego używania kodu,String.Join
jak pokazano w drugiej odpowiedziUżyj zagregowanych zapytań takich jak to:
To daje:
Agregacja to funkcja, która pobiera zbiór wartości i zwraca wartość skalarną. Przykłady z T-SQL obejmują min, max i sumę. Zarówno VB, jak i C # mają obsługę agregatów. Zarówno VB, jak i C # obsługują agregacje jako metody rozszerzenia. Używając notacji kropkowej, po prostu wywołujemy metodę na obiekcie IEnumerable .
Pamiętaj, że agregowane zapytania są wykonywane natychmiast.
Więcej informacji - MSDN: Zagregowane zapytania
Jeśli naprawdę chcesz
Aggregate
użyć wariantu użycia przy użyciuStringBuilder
zaproponowanego w komentarzu CodeMonkeyKing, który byłby mniej więcej taki sam jak zwykły kod, wString.Join
tym dobra wydajność dla dużej liczby obiektów:źródło
""
, pierwszą użytą wartościącurrent
jest pusty ciąg. Tak więc, dla 1 lub więcej elementów, zawsze będziesz,
na początku łańcucha.W .NET 4, nowe przeciążenie na
string.Join
który akceptujeIEnumerable<string>
. Kod wyglądałby wtedy następująco:źródło
Dlaczego warto korzystać z Linq?
To działa idealnie i akceptuje wszystko,
IEnumerable<string>
o ile pamiętam. Nie potrzebaAggregate
tu nic, co jest o wiele wolniejsze.źródło
String.Join(",", s.ToArray())
ze starszych wersji.Czy spojrzałeś na metodę rozszerzenia Aggregate?
źródło
Prawdziwy przykład z mojego kodu:
Zapytanie to obiekt, który ma właściwość Name, która jest łańcuchem, i chcę, aby nazwy wszystkich zapytań na wybranej liście były oddzielone przecinkami.
źródło
Oto połączone podejście Join / Linq, na którym zdecydowałem się po zapoznaniu się z innymi odpowiedziami i problemami poruszonymi w podobnym pytaniu (mianowicie, że agregacja i konkatenat zawodzą z 0 elementami).
string Result = String.Join(",", split.Select(s => s.Name));
lub (jeśli
s
nie jest łańcuchem)string Result = String.Join(",", split.Select(s => s.ToString()));
StringBuilder
) do wdrożeniaI oczywiście Join zajmuje się nieprzyjemnym końcowym przecinkiem, który czasem wymyka się innym podejściom (
for
,foreach
), dlatego przede wszystkim szukałem rozwiązania Linq.źródło
.Select()
tego typu zapewnia łatwe miejsce do modyfikacji każdego elementu podczas tej operacji. Na przykład zawijanie każdego przedmiotu taką postaciąstring Result = String.Join(",", split.Select(s => "'" + s + "'"));
Możesz użyć
StringBuilder
wAggregate
:(
Select
Jest tam tylko po to, aby pokazać, że możesz zrobić więcej rzeczy LINQ.)źródło
new[] {"one", "two", "three"}.Aggregate(new StringBuilder(), (sb, s) =>{if (sb.Length > 0) sb.Append(", ");sb.Append(s);return sb;}).ToString();
if (length > 0)
linq i wyjmując go.new[] {"", "one", "two", "three"}.Aggregate(new StringBuilder(), (sb, s) => (String.IsNullOrEmpty(sb.ToString())) ? sb.Append(s) : sb.Append(", ").Append(s)).ToString();
szybkie dane wydajności dla przypadku StringBuilder vs Select & Aggregate dla ponad 3000 elementów:
Test jednostkowy - czas trwania (sekundy)
LINQ_StringBuilder - 0,0036644
LINQ_Select.Aggregate - 1.8012535
źródło
Zawsze używam metody rozszerzenia:
źródło
string.Join
w .net 4 może już wziąćIEnumerable<T>
dowolny dowolnyT
.Mówiąc „ super fajny sposób LINQ ”, możesz mówić o tym, jak LINQ sprawia, że programowanie funkcjonalne jest o wiele smaczniejsze przy użyciu metod rozszerzenia. Mam na myśli cukier syntaktyczny, który pozwala na łączenie funkcji w wizualnie liniowy sposób (jeden po drugim) zamiast zagnieżdżania (jeden wewnątrz drugiego). Na przykład:
można napisać w ten sposób:
Możesz zobaczyć, jak drugi przykład jest łatwiejszy do odczytania. Możesz także zobaczyć, jak można dodać więcej funkcji przy mniejszej liczbie problemów z wcięciem lub Lispy zamykających pojawiających się na końcu wyrażenia.
Wiele innych odpowiedzi
String.Join
mówi, że jest to najlepsza droga, ponieważ jest najszybsza lub najprostsza do odczytania. Ale jeśli weźmiesz moją interpretację „ super fajnego sposobu LINQ ”, odpowiedzią jest użycie,String.Join
ale zapakuj ją w metodę rozszerzenia w stylu LINQ, która pozwoli ci połączyć twoje funkcje w przyjemny wizualnie sposób. Więc jeśli chcesz pisać,sa.Concatenate(", ")
musisz po prostu stworzyć coś takiego:Zapewni to kod, który jest tak samo wydajny jak bezpośrednie wywołanie (przynajmniej pod względem złożoności algorytmu), aw niektórych przypadkach może sprawić, że kod będzie bardziej czytelny (w zależności od kontekstu), szczególnie jeśli inny kod w bloku używa stylu funkcji łańcuchowej .
źródło
Istnieją różne alternatywne odpowiedzi na to poprzednie pytanie - które wprawdzie było ukierunkowane na tablicę liczb całkowitych jako źródło, ale otrzymało uogólnione odpowiedzi.
źródło
Tutaj używa czystego LINQ jako pojedynczego wyrażenia:
I to jest cholernie szybkie!
źródło
Oszukam trochę i wyrzucę na to nową odpowiedź, która wydaje się podsumowywać to, co najlepsze tutaj, zamiast umieszczać to w komentarzu.
Możesz więc wstawić jedną linię:
Edycja: albo najpierw będziesz chciał sprawdzić, czy nie ma pustego wyliczenia, albo dodaj
.Replace("\a",string.Empty);
na końcu wyrażenia. Chyba starałem się być trochę zbyt mądry.Odpowiedź od @ a.friend może być nieco bardziej wydajna, nie jestem pewien, co robi Replace pod maską w porównaniu do Remove. Jedynym innym zastrzeżeniem jest to, że z jakiegoś powodu chciałbyś połączyć łańcuchy zakończone ... straciłbyś separatory ... Uważam to za mało prawdopodobne. W takim przypadku masz do wyboru inne fantazyjne postacie .
źródło
Możesz połączyć LINQ i
string.join()
całkiem skutecznie. Tutaj usuwam element z łańcucha. Są też lepsze sposoby na zrobienie tego, ale oto:źródło
Tutaj jest duży wybór. Możesz użyć LINQ i StringBuilder, aby uzyskać wyższą wydajność:
źródło
builder.Length > 0
ForEach i usuwając pierwszy przecinek po ForEachZrobiłem następujące szybkie i brudne podczas analizowania pliku dziennika IIS przy użyciu linq, działał on całkiem dobrze 1 milion linii (15 sekund), chociaż wystąpił błąd braku pamięci przy próbie 2 milionów linii.
Prawdziwym powodem, dla którego użyłem linq, był Distinct (), którego potrzebowałem wcześniej:
źródło
Blogowałem o tym jakiś czas temu, to, co zrobiłem, wydaje się być dokładnie tym, czego szukasz:
http://ondevelopment.blogspot.com/2009/02/string-concatenation-made-easy.html
W poście na blogu opisz, jak zaimplementować metody rozszerzeń, które działają na IEnumerable i noszą nazwy Concatenate, pozwoli to napisać takie rzeczy jak:
Lub bardziej skomplikowane rzeczy, takie jak:
źródło