2013-05-08 14 views
10

Obecnie próbuję rzeczy w Scala, próbując przyzwyczaić się do programowania funkcjonalnego, a także ponownie pochylać nowy język (od niedawna minęło trochę czasu).Scalanie listy ciągów przy użyciu mkString vs foldRight

Teraz lista łańcuchów, jeśli chcę połączyć je w jeden długi ciąg (np. "scala", "is", "fun" => "scalaisfun") wymyśliłem jeden sposób, aby to zrobić, to zrobić foldRight i zastosować konkatenację na odpowiednich elementach. Innym sposobem, wprawdzie znacznie prostszym, jest wywołanie mkString.

Sprawdziłem github, ale nie mogłem znaleźć kodu źródłowego dla odpowiednich funkcji (jakakolwiek pomoc na tym się liczy), więc nie jestem pewien, w jaki sposób funkcje są zaimplementowane. Z góry mojej głowy, myślę, że mkString jest bardziej elastyczny, ale czuje, że może być gdzieś w implementacji foldRight. Czy jest w tym jakaś prawda?

W przeciwnym razie skaladoki wspominają o mkString wywołaniach mkString dla każdego odpowiedniego elementu. Widząc, że są one już ciągami na początek, może to być jeden punkt ujemny dla tego konkretnego przypadku w przypadku mkString. Wszelkie uwagi na temat zalet i wad obu metod w odniesieniu do wydajności, prostoty/elegancji itp.?

+0

Oto źródło mkString, jeśli jesteś zainteresowany. https://www.assembla.com/code/scala-eclipse-toolchain/git/nodes/src/library/scala/collection/TraversableOnce.scala?rev=9752caefeb97123f195b32b4166577e59bf22bce#ln262 – sberry

Odpowiedz

17

Prosta odpowiedź: użyj mkString.

someString.toStringreturns ten sam obiekt.

mkString jest realizowany z pojedynczym StringBuilder i tworzy tylko 1 nowy ciąg. Z numerem foldLeft utworzysz nowe ciągi znaków: N-1.

Można użyć StringBuilder w foldLeft, będzie to tak szybko, jak mkString, ale mkString jest krótszy:

strings.foldLeft(new StringBuilder){ (sb, s) => sb append s }.toString 
strings.mkString // same result, at least the same speed 
+1

Ta sama prędkość nie jest całkowicie poprawna w twoim przykładzie foldLeft, użycie StringBuilder bez odpowiedniej początkowej pojemności może zakończyć się tworzeniem więcej niż jednego łańcucha w zależności od danych wejściowych, nie jest pewne, czy mkstring wykonuje iteracje po raz pierwszy w celu określenia odpowiedniej pojemności StringBuilder, ale jeśli tak jest, to nie są one takie same brak gwarancji, że albo utworzy tylko 1 nowy ciąg znaków. –

2

Im pamięć służy, mkString używa StringBuilder do budowania String, który jest wydajny. Możesz zrobić to samo, używając Scala StringBuilder jako akumulatora do foldRight, ale po co zawracać sobie głowę, jeśli mkString może już dla ciebie zrobić wszystkie dobre rzeczy. Plus mkString daje dodatkową korzyść, również z opcjonalnym ogranicznikiem. Możesz to zrobić w foldRight, ale jest już gotowe dla ciebie z mkString

5

Nie używaj foldRight chyba że naprawdę potrzebują, jak będzie to przepełnienie stosu na swój duży kolekcje (dla niektórych typów kolekcji). foldLeft lub fold będzie działać (nie przechowuje pośrednich danych na stosie), ale będzie wolniejszy i bardziej niezręczny niż mkString. Jeśli lista nie jest pusta, działają również reduce i reduceLeft.

Powiązane problemy