Saya memiliki file yang berisi beberapa ribu angka, masing-masing pada barisnya sendiri:
34
42
11
6
2
99
...
Saya ingin menulis skrip yang akan mencetak jumlah semua angka dalam file. Saya punya solusi, tetapi tidak terlalu efisien. (Butuh beberapa menit untuk menjalankannya.) Saya mencari solusi yang lebih efisien. Ada saran?
awk
danbc
). Ini semua selesai menambahkan satu juta angka dalam waktu kurang dari 10 detik. Lihatlah itu dan lihat bagaimana hal itu dapat dilakukan dalam cangkang murni.Jawaban:
Untuk Perl one-liner, pada dasarnya hal yang sama dengan
awk
solusi dalam jawaban Ayman Hourieh :Jika Anda penasaran dengan apa yang dilakukan Perl one-liners, Anda dapat menjelaskannya:
Hasilnya adalah versi yang lebih verbose dari program ini, dalam bentuk yang tidak seorang pun akan menulis sendiri:
Hanya untuk cekikikan, saya mencoba ini dengan file yang berisi 1.000.000 angka (dalam kisaran 0 - 9.999). Di Mac Pro saya, ia mengembalikan hampir secara instan. Itu terlalu buruk, karena saya berharap menggunakan
mmap
akan sangat cepat, tetapi pada saat yang sama:sumber
while { }
loop di sekitar program Anda. Jika Anda memasukkan ke} ... {
dalam, maka Anda memilikinyawhile { } ... { }
. Jahat? Sedikit.-MO=Deparse
opsi! Padahal pada topik terpisah.Anda dapat menggunakan awk:
sumber
-F '\t'
opsi jika bidang Anda berisi spasi dan dipisahkan oleh tab.Sejauh ini tidak ada solusi yang digunakan
paste
. Ini dia:Sebagai contoh, hitung Σn di mana 1 <= n <= 100000:
(Bagi yang penasaran,
seq n
akan mencetak urutan angka dari1
ken
diberikan angka positifn
.)sumber
seq 100000 | paste -sd+ - | bc -l
pada Mac OS X Bash shell. Dan sejauh ini ini adalah solusi termanis dan tidak tersentuh!Hanya untuk bersenang-senang, mari patok:
Saya membatalkan menjalankan sed setelah 5 menit
Saya sudah menyelam ke lua, dan cepat:
dan sementara saya memperbarui ini, ruby:
Saran Heed Ed Morton: menggunakan
$1
vs menggunakan
$0
sumber
tr
solusinya.$0
alih-alih$1
karena awk melakukan pemisahan bidang (yang jelas membutuhkan waktu) jika ada bidang yang disebutkan secara khusus dalam skrip tetapi tidak sebaliknya.Pilihan lain adalah menggunakan
jq
:-s
(--slurp
) membaca baris input ke dalam array.sumber
Ini Bash langsung:
sumber
Ini satu kalimat lagi
Ini mengasumsikan angkanya bilangan bulat. Jika Anda membutuhkan desimal, cobalah
Sesuaikan 2 dengan jumlah desimal yang dibutuhkan.
sumber
Saya lebih suka menggunakan GNU datamash untuk tugas-tugas seperti itu karena lebih ringkas dan dapat dibaca daripada perl atau awk. Sebagai contoh
di mana 1 menunjukkan kolom data pertama.
sumber
sumber
Saya lebih suka menggunakan R untuk ini:
sumber
(sama dengan jawaban brian d foy, tanpa 'END')
sumber
perl -MO=Deparse
untuk melihat bagaimana perl mem-parsing program. atau dokumen untuk perlrun: perldoc.perl.org/perlrun.html (cari -n). perl membungkus kode Anda dengan {} jika Anda menggunakan -n sehingga menjadi program yang lengkap.Lebih ringkas:
sumber
time python -c "print(sum([float(s) for s in open('random_numbers','r')]))"
Perl 6
sumber
Hanya untuk bersenang-senang, mari kita lakukan dengan PDL , mesin matematika array Perl!
rcols
membaca kolom menjadi matriks (1D dalam kasus ini) dansum
(kejutan) menjumlahkan semua elemen matriks.sumber
Berikut adalah solusi menggunakan python dengan ekspresi generator. Diuji dengan sejuta angka pada laptop saya yang kasar.
sumber
map()
:map(float, sys.stdin)
Saya tidak bisa hanya lewat ... Ini Haskell one-liner saya. Ini sebenarnya cukup mudah dibaca:
Sayangnya tidak ada
ghci -e
untuk hanya menjalankannya, sehingga perlu fungsi utama, cetak dan kompilasi.Untuk memperjelas, kami membaca seluruh input (
getContents
), membaginya denganlines
,read
sebagai angka dansum
.<$>
adalahfmap
operator - kami menggunakannya bukan aplikasi fungsi biasa karena yakin ini semua terjadi di IO.read
perlu tambahanfmap
, karena juga ada dalam daftar.Berikut ini adalah upgrade yang aneh untuk membuatnya bekerja dengan float:
sumber
sumber
Menjalankan skrip R
Saya telah menulis skrip R untuk mengambil argumen nama file dan menjumlahkan baris.
Ini dapat dipercepat dengan paket "data.table" atau "vroom" sebagai berikut:
Benchmarking
Data pembandingan yang sama dengan @glenn jackman .
Dibandingkan dengan panggilan R di atas, menjalankan R 3.5.0 sebagai skrip dapat dibandingkan dengan metode lain (pada server Linux Debian yang sama).
R script dengan readLines
R script dengan data.table
R script dengan vroom
Perbandingan dengan bahasa lain
Untuk referensi di sini karena beberapa metode lain disarankan pada perangkat keras yang sama
Python 2 (2.7.13)
Python 3 (3.6.8)
Ruby (2.3.3)
Perl (5.24.1)
Awk (4.1.4)
C (dentang versi 3.3; gcc (Debian 6.3.0-18) 6.3.0)
Perbarui dengan bahasa tambahan
Lua (5.3.5)
tr (8.26) harus diberi batas waktu dalam bash, tidak kompatibel dengan zsh
sed (4.4) harus diberi batas waktu dalam bash, tidak kompatibel dengan zsh
catatan: panggilan sed tampaknya bekerja lebih cepat pada sistem dengan lebih banyak memori yang tersedia (perhatikan kumpulan data yang lebih kecil digunakan untuk benchmarking sed)
Julia (0.5.0)
Perhatikan bahwa seperti dalam R, metode file I / O memiliki kinerja yang berbeda.
sumber
C ++ "satu garis":
sumber
Lain untuk bersenang-senang
atau bash lain saja
Tetapi solusi awk mungkin yang terbaik karena paling kompak.
sumber
C selalu menang untuk kecepatan:
Waktu untuk angka 1M (mesin / input yang sama dengan jawaban python saya):
sumber
Dengan Ruby:
sumber
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.Saya tidak tahu apakah Anda bisa mendapatkan jauh lebih baik dari ini, mengingat Anda perlu membaca seluruh file.
sumber
$_
adalah variabel default. Operator baris masukan,<>
, menempatkan hasil itu di sana secara default ketika Anda menggunakan<>
diwhile
.$_
adalah variabel topik - ia bekerja seperti 'itu'. Dalam hal ini,<>
berikan setiap baris untuk itu. Itu akan digunakan di sejumlah tempat untuk mengurangi kekacauan kode dan membantu dengan menulis satu baris. Script mengatakan "Tetapkan jumlah ke 0, baca setiap baris dan tambahkan ke jumlah, lalu cetak jumlahnya."$sum
. Karena ini sangat sederhana, Anda bahkan dapat menggunakan pengubah pernyataanwhile
:$sum += $_ while <>; print $sum;
Saya belum menguji ini tetapi seharusnya berhasil:
Anda mungkin harus menambahkan "\ n" ke string sebelum bc (seperti via echo) jika bc tidak memperlakukan EOF dan EOL ...
sumber
bc
mengeluarkan kesalahan sintaksis karena trailing "+" dan kurangnya baris baru di akhir. Ini akan berhasil dan menghilangkan penggunaan yang tidak berguna daricat
:{ tr "\n" "+" | sed 's/+$/\n/'| bc; } < numbers2.txt
atau<numbers2.txt tr "\n" "+" | sed 's/+$/\n/'| bc
tr "\n" "+" <file | sed 's/+$/\n/' | bc
Ini yang lain:
sumber
Anda dapat melakukannya dengan Alacon - utilitas baris perintah untuk basis data Alasql .
Ini bekerja dengan Node.js, jadi Anda perlu menginstal Node.js dan kemudian paket Alasql :
Untuk menghitung jumlah dari file TXT Anda dapat menggunakan perintah berikut:
sumber
Hal ini tidak mudah untuk mengganti semua lini baru
+
, menambah0
dan mengirimkannya keRuby
juru?Jika tidak punya
irb
, Anda dapat mengirimnya kebc
, tetapi Anda harus menghapus semua baris baru kecuali yang terakhirecho
. Lebih baik digunakantr
untuk ini, kecuali jika Anda memiliki gelar PhD dised
.sumber
In Go:
sumber
Varian bash
sumber
Dalam shell menggunakan awk, saya telah menggunakan skrip di bawah ini untuk melakukannya:
sumber