C++11 といくつかの標準アルゴリズムを使用した簡単な例で遊んでいますが、 または を使用するかどうかはわかりませstd::accumulate
んstd::for_each
。問題は、単語の文字数を数えることです。たとえば、「abracadabra」と入力すると、次のようになります。
'a' => 5
'b' => 2
'c' => 1
'd' => 1
'r' => 2
私の最初のカットは を使用することでしたstd::accumulate
。これが自然に見える理由は、値 (一連の周波数) を実際に累積しているためです。また、私は最近関数型プログラミングを行っていて、リストを折りたたむaccumulate
ことの自然な翻訳のように思えました。
vector<int> charsInWord(const string& text)
{
return
std::accumulate(text.begin(), text.end(), vector<int>(256),
[] (const vector<int>&v, char c)
{
vector<int> v2(v);
v2[c]++;
return v2;
} );
}
ただし、この解決策はかなり面倒に思え、正しくなるまでに少し時間がかかりました。さらに、新しいmove
セマンティクスを使用しても、不必要なコピーがないことを確信できませんでした。
だから私はfor_each
代わりに行きました。
vector<int> charsInWord2(const string& text)
{
vector<int> charCounts(256);
std::for_each(text.begin(), text.end(),
[&] (char c)
{
charCounts[c]++;
} );
return charCounts;
}
これはおそらく書きやすく、理解しやすいものであり、その効率性については確かに満足しています (ただし、 の宣言的で関数的なスタイルが恋しいですaccumulate
)。
これらの例で、どちらか一方を優先する正当な理由はありますか? これまでのコメントと回答から、私が蓄積している値が自明ではない場合、たとえばstl
コンテナではなくコンテナを言うと、実際に「蓄積」している場合でも、int
常に を優先する必要があるようです。for_each
完全を期すために、これをコンパイルしてテストするための残りのコードを以下に示します。
#include <string>
#include <vector>
#include <numeric> // accumulate
#include <algorithm> // for_each
using std::string;
using std::vector;
#include <iostream>
// ... insert code above ...
int main(int argc, char* argv[])
{
const vector<int> charCounts = charsInWord("abracadabra");
for(size_t c=0; c<charCounts.size(); ++c) {
const int count = charCounts[c];
if (count > 0) {
std::cout << "'" << static_cast<char>(c) << "'" << " => " << count << "\n";
}
}
return 0;
}