Saya memiliki file CSV users.csv
dengan daftar Nama pengguna, ID pengguna, dan data lainnya:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"Paul McCartny", 30923833, "left", "black"
"Ringo Starr", 77392318, "right", "blue"
"George Harrison", 72349482, "left", "green"
Di file lain toremove.txt
saya punya daftar ID pengguna:
30923833
77392318
Apakah ada cara pintar dan efisien untuk menghapus semua baris dari users.csv
file yang berisi ID toremove.txt
? Saya telah menulis aplikasi Python sederhana untuk mem-parsing dua file dan menulis ke file baru hanya baris-baris yang tidak ditemukan toremove.txt
, tetapi ini sangat lambat. Mungkin beberapa sed
atau awk
sihir dapat membantu di sini?
Ini adalah hasil yang diinginkan, dengan mempertimbangkan contoh di atas:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"
linux
command-line
text-processing
dotancohen
sumber
sumber
users.csv
file, dan n untuk baristoremove.txt
. Saya tidak begitu yakin bagaimana melakukannya dengan kompleksitas yang lebih rendah. Inti dari itu adalah:for u in users: if not any(toremove in u): outputfile.write(u)
. Saya dapat mempostingnya ke Code Review.toremove.txt
, menyimpan entri sebagai kunci . Iterate users.csv, cetak di mana id tidak ada dalam dikt. Anda mendapatkan pemrosesan O (n) untuk keduanyatoremove.txt
danusers.csv
, dan O (n) penggunaan memori untuktoremove.txt
(yang mungkin relatif kecil)Jawaban:
Dengan
grep
, Anda dapat melakukan:Dengan
awk
:sumber
awk
solusi adalah sangat sensitif terhadap file yang diformat persis seperti yang ditunjukkan dalam pertanyaan. Paling mencolok, jika nama hanya satu kata / token (yaitu, tidak mengandung spasi; misalnya,"Bono"
) atau lebih dari dua token (yaitu, mengandung lebih dari satu spasi; misalnya,"Sir Paul McCartney"
), itu akan melewati bahkan jika kecocokan userid. Kurang jelas, hal yang sama terjadi jika tidak ada ruang antara koma pertama dan userid, atau jika ada lebih dari satu ruang (misalnya,"John Lennon", 90123412, …
).awk
solusigrep
Inilah
awk
jawaban Gnouc , yang dimodifikasi menjadi buta-ruang:Karena hanya menggunakan koma (dan bukan spasi) sebagai pembatas,
$1
is"John Lennon"
,$2
is90123412
(dengan spasi terdepan), dll. Jadi kami menggunakangensub
untuk menghapus sejumlah spasi terkemuka$2
sebelum kita memeriksa apakah (userid) ada ditoremove.txt
file.sumber
OK cara ruby: jika Anda memiliki daftar string dalam file, dan Anda ingin menghapus semua baris dari file lain yang bahkan mengandung string apa pun di file pertama (dalam hal ini menghapus "file2" dari "file1") file ruby :
sayangnya dengan file "untuk menghapus" besar ini tampaknya menurunkan kompleksitas-bijaksana untuk O (N ^ 2) (asumsi saya adalah regexp memiliki banyak pekerjaan yang harus dilakukan), tetapi masih mungkin berguna bagi seseorang di luar sana (jika Anda ingin lebih dari menghapus garis penuh). Mungkin lebih cepat dalam kasus-kasus tertentu.
Pilihan lain jika Anda ingin kecepatan adalah menggunakan mekanisme pemeriksaan hash yang sama, tetapi untuk "mengurai" garis untuk string yang mungkin cocok, kemudian membandingkannya dengan hash Anda.
Dalam ruby, mungkin terlihat seperti ini:
Lihat juga jawaban Scott, mirip dengan jawaban awk yang diajukan di sana, dan menghindari kompleksitas O (N ^ 2) (phew).
sumber