Cách nhanh nhất để xóa các bản sao trong danh sách từ lớn?


14

Tôi cần phải lặp lại một danh sách từ lớn. Tôi đã thử một số lệnh và thực hiện một số nghiên cứu ở đâyở đây nơi họ giải thích rằng cách nhanh nhất để sao chép một danh sách từ dường như là sử dụng awk.

awk -> O (n)? sắp xếp -> O (n log n)?

Tuy nhiên tôi thấy rằng điều này dường như không đúng. Đây là kết quả thử nghiệm của tôi:

sort -u input.txt -o output.txt 


người dùng thực 0m12.446s 0m11.347s
sys 0m0.906s

awk '!x[$0]++' input.txt > output.txt

thực 0m47.221s
0m45.419s dùng
sys 0m1.260s

Vì vậy, sử dụng sort -u nhanh hơn 3,7 lần. Tại sao lại thế này? Có một phương pháp thậm chí nhanh hơn để làm trùng lặp?

****** TÌM HIỂU

Như ai đó đã chỉ ra trong các bình luận, có thể là danh sách từ của tôi đã được sắp xếp ở một mức độ nào đó. Để loại trừ khả năng này, tôi đã tạo hai danh sách từ bằng cách sử dụng tập lệnh python này .

Danh sách1 = 7 Mb
Danh sách2 = 690 Mb

Kết quả AWK:
List1
thực 0m1.643s
người dùng 0m1.565s
sys 0m0.062s

List2
thực 2m6.918s
2m4.499s dùng
sys 0m1.345s

Kết quả SORT:
List1
thực 0m0.724s
người dùng 0m0.666s
sys 0m0.048s

List2
thực 1m27.254s
1m25.013s dùng
sys 0m1.251s


Có thể là dữ liệu đầu vào của bạn đã được sắp xếp?
iruvar

Tôi sẽ tạo một danh sách ngẫu nhiên với các số và kiểm tra chỉ để đảm bảo
karlpy

2
Ký hiệu Big O là về những gì xảy ra khi độ dài đầu vào đạt tới vô hạn: nó cho bạn biết đó là một thuật toán có tỷ lệ với đầu vào lớn. Một số thuật toán hoạt động tốt hơn trên kích thước đầu vào nhỏ.
ctrl-alt-delor

1
Karlpy, bạn đã thực hiện theo thứ tự nào, trước tiên hay sắp xếp? Điều đó có thể tạo ra sự khác biệt do bộ nhớ đệm tập tin
iruvar

1
@karlpy: "Tôi đã thay đổi tên tệp ..." Nếu bạn muốn đổi tên tệp, điều đó không đủ tốt. Đổi tên một tệp chỉ liên kết một tên mới với inode cũ, mà vẫn trỏ đến cùng các khối dữ liệu cũ. Nếu chúng được lưu trữ, chúng vẫn được lưu trữ. ISTM rằng một kỹ thuật tốt hơn nhiều sẽ là (1) tạo một bản sao của tệp và sau đó (2) chạy một lệnh trên một tệp và (3) chạy lệnh khác trên tệp khác.
Scott

Câu trả lời:


3

Bạn đang hỏi sai câu hỏi hoặc đặt câu hỏi sai và trong ngăn xếp sai, đây là một câu hỏi tốt hơn để hỏi trong lập trình / ngăn xếp chồng để mọi người đưa ra câu trả lời dựa trên các thuật toán được sử dụng bên trong awk và sort.

PS: cũng cần thiết với nawk, mawk và gawk để cung cấp cho chúng tôi thêm một số chi tiết để "khoanh vùng";) và thực hiện các bước chạy như 100 lần mỗi lần với độ lệch tối thiểu, tối đa, avg và tiêu chuẩn.

Bất kỳ trường hợp nào trở lại câu hỏi, từ CompSci 210, đó là về các thuật toán được sử dụng. Sắp xếp sử dụng một số, tùy thuộc vào kích thước và các ràng buộc bộ nhớ mà nó đạt được để lưu các tệp ra đĩa trong các tệp tạm thời được hợp nhất được sắp xếp một khi nó hết bộ nhớ và bạn sẽ phải xem mã nguồn để xem lệnh sort (1) cụ thể sử dụng trên HĐH cụ thể mà bạn đang chạy, nhưng từ kinh nghiệm, nó sẽ tải vào bộ nhớ nhiều nhất có thể, thực hiện một số cách sắp xếp nhanh trên nó, ghi ra đĩa, rửa lặp lại và tại kết thúc nó sẽ thực hiện hợp nhất - sắp xếp các tệp được sắp xếp nhỏ. Vì vậy, ở đây bạn sẽ có O (n * log2 (N)) cho các bộ phận và sau đó là một hoạt động hợp nhất O (n * log (n)) gần đúng

awk: Cơ chế x [$ 0] ++ là "giả sử" để sử dụng băm. NHƯNG vấn đề với băm, một hoạt động "tra cứu" được cho là O (1), là va chạm và xử lý va chạm. Điều này có thể gây ra sự cố khi dữ liệu không được lan truyền một cách độc đáo, cũng không làm đầy các thùng, v.v. và trong các danh sách lớn, việc băm có thể là một vấn đề lớn về bộ nhớ nếu việc xử lý các va chạm không được thực hiện đúng (và bạn có thể cần phải điều chỉnh các thuật toán băm cho dữ liệu dự kiến), và sau đó bạn cần xem hiệu suất của các hàm băm thực tế và sau đó O (1) có thể gần hơn với O (log (n)) cho các phần chèn (Ie. O (1) cho tìm kiếm đầu tiên và nếu nó KHÔNG tồn tại, bạn thêm nó có thể là O (log (n))), và sau đó n * O (1) trở thành * O (log (n)) = > O (n * log (n)), chưa kể bạn cũng đang làm mọi thứ theo cách "diễn giải" :)


-2

Sự khác biệt về tốc độ là do 'sort' là một lệnh ( liên kết ), trong khi 'awk' là ngôn ngữ lập trình ( liên kết ).

Lệnh 'sort' nhận đầu vào và đầu ra trở lại. Trong khi đó 'awk' là ngôn ngữ lập trình, đầu tiên diễn giải mã (lệnh đầu cuối) sau đó bắt đầu xử lý nó. Đơn giản như thế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.