Apa cara yang baik untuk menemukan jumlah semua elemen dalam std::vector
?
Misalkan saya memiliki vektor std::vector<int> vector
dengan beberapa elemen di dalamnya. Sekarang saya ingin mencari jumlah semua elemen. Apa cara yang berbeda untuk hal yang sama?
std::accumulate
di Boost? (Jika demikian, mengapa?) Apakah Anda mencari fungsi yang melakukan sesuatu yang miripstd::accumulate
? (Jika ya, apa?)std::accumulate
, mungkin Anda juga ingin itu berbeda dalam beberapa hal (jika tidak, Anda bisa menggunakanstd::accumulate
); apa perbedaanstd::accumulate
yang Anda cari?Jawaban:
Sebenarnya ada beberapa metode.
C ++ 03
Klasik untuk loop:
Menggunakan algoritma standar:
Catatan Penting: Jenis argumen terakhir digunakan tidak hanya untuk nilai awal, tetapi untuk jenis hasil juga. Jika Anda meletakkan int di sana, int akan mengakumulasikan bahkan jika vektor telah mengambang. Jika Anda menjumlahkan angka floating-point, ubah
0
ke0.0
atau0.0f
(terima kasih kepada nneonneo). Lihat juga solusi C ++ 11 di bawah ini.C ++ 11 dan lebih tinggi
b. Secara otomatis melacak jenis vektor bahkan jika terjadi perubahan di masa depan:
Menggunakan
std::for_each
:Menggunakan rentang berbasis untuk loop (terima kasih kepada Roger Pate):
sumber
std::for_each
dengan functor, hanya dibutuhkan lebih banyak baris kode untuk didefinisikan daripada lambda C ++ 0x.for_each
?accumulate
akan lebih ringkas (bahkan jika itu tidak membutuhkan lambda)accumulate
di dalamfor_each
tetapi bukankah contoh ini berguna (untuk tujuan pembelajaran) karena ini menunjukkan bahwa kita juga dapat memiliki lambdas :-)accumulate
. Jenis argumen terakhir digunakan tidak hanya untuk nilai awal, tetapi untuk jenis hasilnya. Jika Anda meletakkan diint
sana, itu akan menumpukint
bahkan jika vektor memilikifloat
. Hasilnya bisa sedikit salah, dan kompiler akan mengembalikan hasilnya ke float tanpa memberi tahu Anda.for_each
jika Anda milikiaccumulate
?Cara termudah adalah dengan menggunakan
std:accumuate
darivector<int> A
:sumber
Prasoon telah menawarkan sejumlah cara yang berbeda (dan bagus) untuk melakukan ini, tidak ada yang perlu diulang di sini. Saya ingin menyarankan pendekatan alternatif untuk kecepatan.
Jika Anda akan melakukan ini sedikit, Anda mungkin ingin mempertimbangkan "sub-classing" vektor Anda sehingga sejumlah elemen dipertahankan secara terpisah ( sebenarnya bukan sub-classing vector yang rapuh karena kurangnya destructor virtual - Saya berbicara lebih banyak tentang kelas yang berisi jumlah dan vektor di dalamnya,
has-a
daripadais-a
, dan menyediakan metode seperti vektor).Untuk vektor kosong, jumlahnya diatur ke nol. Pada setiap penyisipan ke vektor, tambahkan elemen yang dimasukkan ke jumlah. Pada setiap penghapusan, kurangi. Pada dasarnya, apa pun yang dapat mengubah vektor yang mendasarinya disadap untuk memastikan jumlah dijaga konsisten.
Dengan begitu, Anda memiliki metode O (1) yang sangat efisien untuk "menghitung" jumlah pada setiap saat (hanya mengembalikan jumlah yang saat ini dihitung). Penyisipan dan penghapusan akan memakan waktu sedikit lebih lama saat Anda menyesuaikan total dan Anda harus mempertimbangkan kinerja ini.
Vektor di mana jumlah dibutuhkan lebih sering daripada vektor diubah adalah yang kemungkinan mendapat manfaat dari skema ini, karena biaya perhitungan jumlah diamortisasi atas semua akses. Jelas, jika Anda hanya membutuhkan jumlah setiap jam dan vektor berubah tiga ribu kali per detik, itu tidak akan cocok.
Sesuatu seperti ini sudah cukup:
Jelas, itu pseudo-code dan Anda mungkin ingin memiliki lebih banyak fungsi, tetapi itu menunjukkan konsep dasar.
sumber
std::vector
tidak dimaksudkan untuk subkelas.has-a
vektor di dalamnya, daripada menjadi subkelas yang tepat (is-a
).operator[](int)
, non-const iterators ...Mengapa melakukan penjumlahan ke depan ketika Anda bisa melakukannya mundur ? Diberikan:
Kita bisa menggunakan subskrip, menghitung mundur:
Kita dapat menggunakan "subskrip," yang dicentang jangkauan, menghitung mundur (untuk berjaga-jaga):
Kita dapat menggunakan iterator terbalik dalam for loop:
Kita bisa menggunakan forward iterator, iterasi mundur, dalam for loop (oooh, tricky!):
Kita dapat menggunakan
accumulate
dengan iterator terbalik:Kita dapat menggunakan
for_each
dengan ekspresi lambda menggunakan iterator terbalik:Jadi, seperti yang Anda lihat, ada banyak cara untuk menjumlahkan vektor ke belakang sama halnya dengan menjumlahkan vektor ke depan, dan beberapa di antaranya jauh lebih menarik dan menawarkan peluang yang jauh lebih besar untuk kesalahan satu per satu.
sumber
v.size()
.sumber
boost::accumulate
hanyalah pembungkus di sekitarstd::accumulate
.#include <numeric>
danstd::accumulate(v.begin(), v.end(), (int64_t)0);
. Perhatikan bahwa jenis nilai akumulator awal digunakan sebagai jenis akumulator, jadi jika Anda ingin menjumlahkan elemen 8-bit menjadi hasil 64-bit, itulah cara Anda melakukannya.Anda juga bisa menggunakan
std::valarray<T>
seperti iniBeberapa mungkin tidak menemukan cara ini efisien karena ukuran
valarray
kebutuhan harus sebesar ukuran vektor dan inisialisasivalarray
juga akan memakan waktu.Dalam hal itu, jangan gunakan dan anggap sebagai cara lain untuk menyimpulkan urutannya.
sumber
C ++ 0x saja:
Ini mirip dengan BOOST_FOREACH yang disebutkan di tempat lain dan memiliki manfaat kejelasan yang sama dalam situasi yang lebih kompleks, dibandingkan dengan functor stateful yang digunakan dengan akumulasi atau for_each.
sumber
for (int n : v) sum += n;
kefor (auto n : v) sum += n;
itu akan bekerja dengan vektor Template. Saya tahu OP merujuk ke vektor <int>, tetapi cara ini sedikit lebih umum :-)Saya pengguna Perl, permainan yang kami miliki adalah menemukan setiap cara berbeda untuk meningkatkan variabel ... itu tidak terlalu berbeda di sini. Jawaban untuk berapa banyak cara untuk menemukan jumlah elemen vektor di C ++ mungkin
an infinity
...2 sen saya:
Menggunakan BOOST_FOREACH, untuk mendapatkan sintaks iterator jelek:
iterasi pada indeks (sangat mudah dibaca).
Yang lain ini destruktif, mengakses vektor seperti tumpukan:
sumber
start + length
). Iterator yang sebenarnya juga harus mengoptimalkan sepenuhnya. Ingat, ini bukan perl; itu sepenuhnya dikompilasi ke asm, tidak diartikan.sumber
int
indeks astd::vector
secara umum tidak aman.v.size()
mungkin lebih besar dari nilai tertinggi yang dapat disimpanint
(perhatikan bahwa dengan beberapa platform & kompiler target,size_of(int) < size_of(size_t)
). Dalam hal ini, kode Anda akan meluap indeks. std :: vector <T> :: size_type harus dipilih.Ini mudah. C ++ 11 menyediakan cara mudah untuk meringkas elemen vektor.
sumber