2010-10-11 8 views
23

Ich brauche ein Analog von Haskells foldl Funktion, um alle STL-Container zu falten. Die erwartete Signatur ist wie folgt:Wie wird der STL-Behälter gefaltet?

template Iterator, FoldingFunction, Result 
Result foldl(
    Iterator begin, 
    Iterator end, 
    FoldingFunction f, 
    Result initValue); 

Standard-STL hat keine solche Funktion. Hat Boost irgendwelche?

Ich weiß, es ist ziemlich einfach zu implementieren, aber ich würde gerne wissen, ob es eine fertige standardisierte Implementierung gibt.

Und noch eine Frage: Wie falten Sie normalerweise Datenlisten in C++/STL?

+3

Was meinst du mit 'falten' ?? – Konrad

+4

@Konrad: [fold] (http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29) = reduzieren = akkumulieren. – kennytm

+3

@Konrad - eine Datenstruktur in einer bestimmten Reihenfolge verarbeiten und einen Rückgabewert erstellen. http://www.haskell.org/haskellwiki/Fold – DumbCoder

Antwort

37

STL hat eine solche Funktion: std::accumulate. Es ist jedoch in der Kopfzeile <numeric>, nicht <algorithm>.

Eigentlich die Wikipedia page on "Fold" bereits aufgeführt die foldl/foldr Funktionen in den meisten Programmiersprachen, einschließlich C++.

+0

@KennyTM: Vielen Dank für die Wiki-Referenz. – Andrey

+0

Beachten Sie, dass "accumulate" den "value_type" der Iteratorargumente für die interne Akkumulatorvariable verwendet, obwohl Sie einen unterschiedlichen Typ akzeptieren und zurückgeben und andere Typen im funktor-Argument zulassen. – Potatoswatter

+0

@Potatoswatter: Ich sehe dies nicht von akkumulieren Definition: TYPE akkumulieren (Eingang_iterator Start, Eingang_iterator Ende, TYPE val, BinaryFunction f); – Andrey

4

Haben Sie std::accumulate im Header <numeric> betrachtet?

+0

Es ist 'std :: accumulate'. Es ist im 'std' Namensraum, aber im '' Header. :) – jalf

+0

@jalf halten sie kommen. Nur so bleibe ich in der Schlange. : P – wheaties

0

Obwohl scheint der beste Kandidat zu sein, denke ich, dass die Anforderung durch die Verwendung von guten alten for_each auch erreicht werden kann.

Ich nahm die Beispiele aus dem Link in answer of KennyTM und übersetzte sie alle zu for_each. The full code is posted at codepad, finden Sie einige Auszug:

struct result_functor { 
    result_functor(int initial, int multiplier) : 
     result_(initial), multiplier_(multiplier) { 
    } 
    int operator()(int x) { 
     result_ += multiplier_ * x; 
     return result_; 
    } 
    int result_; 
    int multiplier_; 
}; 

const int init = 100; 
const int numbers[] = { 10, 20, 30 }; 

const int accum_sum = std::accumulate(numbers, numbers + 3, init); 
const result_functor for_sum = for_each( 
    numbers, numbers + 3, result_functor(init, +1)); 
assert(accum_sum == for_sum.result_); 
+0

Stateful Funktor 'result_functor' bedeutet undefiniertes Verhalten. – Loom

+0

@Loom Diese Antwort schlägt vor, dass Stateful Funktoren für 'std :: for_each' in Ordnung sind: http://Stackoverflow.com/a/6113053/2348315, ist es falsch? – PeterSW

1

hier ist meine Implementierung std :: akkumulieren

template<typename collection, typename operation> 
typename collection::value_type reduce(collection col, operation op) 
{ 
    return accumulate(col.begin(), col.end(), typename collection::value_type(), op); 
} 

die reduce Mittel in Haskell falten. Und diese Funktionsschablone kann das Programm funktioneller machen :)

+0

Die Verwendung von 'begin (col)' und 'end (col)' würde generischer sein, aber diese Funktion ist ziemlich redundant, da 'accumate' auch direkt aufgerufen werden kann. – sim642

-1

warum nicht gerade;

b_t foldl(b_t (*f)(b_t,a_t),b_t base_case,a_t * in_list){ 
int l = sizeof(inList)/sizeof(a_t); 
b_t carry = base_case; 
for(int i = 0;i<l;i++){ 
    carry = f(carry,in_list[i]); 
    } 
return carry; 
} 

oder rekursiv; // vielleicht könntest du mir mit der richtigen syntax helfen ...

b_t foldl(b_t (*f)(b_t,a_t),b_t base_case,a_t * in_list){ 
return foldl(f,f(base_case,in_list[0]),in_list + 1);  
} 
+2

Weil das nur mit 'b_t',' a_t' und Funktionszeigern funktioniert. Außerdem ist es weniger vertrauenswürdig als die viel häufiger verwendete und getestete Alternative, die in den Standardbibliotheksimplementierungen zu finden ist. – PeterSW

Verwandte Themen