Làm thế nào để xếp hạng số trong mảng bằng Unix?


7

Tôi nghĩ nếu có tồn tại bất kỳ tên nào cho một hàm đơn giản như vậy trả về thứ tự các số trong một mảng. Tôi thực sự thích thực hiện xếp hạng này theo cách tối giản và với các lệnh Unix cơ bản nhưng tôi không thể có bất cứ điều gì trong tâm trí của tôi hơn là tìm kiếm và vòng lặp cơ bản không quá thanh lịch. Giả sử bạn có một dãy số

17 
94 
3 
52 
4 
4 
9

Đầu ra dự kiến ​​trong đó các bản sao chỉ nhận được cùng một ID; Làm thế nào để xử lý các bản sao không quan trọng vì vậy hãy sử dụng các phím tắt:

4 
6 
1 
5 
2 
2 
3        

Động lực: Tôi thấy ngày nay nhiều người dùng sử dụng nhiều cách khác nhau để giải quyết vấn đề này và thực hiện nhiều bước thủ công với Bảng tính; Vì vậy, tôi bắt đầu nghĩ cách tối giản để làm điều đó.

So sánh thuật toán xếp hạng với xếp hạng Trung bình của Google

Trong Bảng tính Google, hãy làm =arrayformula(rank.AVG(A:A,A:A,true))và bạn lấy điểm chuẩn theo thứ tự tăng dần như đầu ra dự kiến ​​đầu tiên

17  5
94  7
3   1
52  6
4   2.5
4   2.5
9   4

nơi bạn thấy rằng thuật toán xếp hạng ban đầu của tôi là sai lệch. Tôi nghĩ rằng để có thể thiết lập vị trí dữ liệu sẽ hữu ích ở đây.


1
Ngoài việc theo thứ tự ngược lại, sự khác biệt "thiên vị" nhỏ đến từ việc đếm các mục trùng lặp là 2 vị trí thay vì một.
JJoao

Câu trả lời:


11

Nếu danh sách đó nằm trong một file, mỗi dòng, tôi sẽ làm một cái gì đó như:

sort -nu file |
  awk 'NR == FNR {rank[$0] = NR; next}
      {print rank[$0]}' - file

Nếu nó là trong một zsh $array:

sorted=(${(nou)array})
for i ($array) echo $sorted[(i)$i]

Đó là nguyên tắc tương tự như đối với awkphiên bản trên, thứ hạng là chỉ mục NR/ (i)trong danh sách các phần tử ( -n/ (n)) được sắp xếp theo thứ tự ( sort/ (o)), duy nhất ( -u/ (u)).

Đối với thứ hạng trung bình của bạn:

sort -n file |
  awk 'NR == FNR {rank[$0] += NR; n[$0]++; next}
  {print rank[$0] / n[$0]}' - file

Cung cấp cho:

5
7
1
6
2.5
2.5
4

(sử dụng sort -rnđể đảo ngược thứ tự như trong phiên bản Bảng tính Google của bạn ).


Vui lòng xem điểm chuẩn xếp hạng trung bình của Google trong cơ thể. Có lẽ, nó có thể đơn giản hóa đề xuất của bạn. Để có thể đặt vị trí tập dữ liệu bị sai lệch và / hoặc không thiên vị sẽ là tuyệt vời.
Léo Léopold Hertz

2
@Masi, xem chỉnh sửa để xếp hạng trung bình. Tôi không theo dõi câu của bạn về vị trí thiên vị / không thiên vịdữ liệu . Có thể câu hỏi của bạn cần nhiều bối cảnh hơn.
Stéphane Chazelas

8
nl x | sort  -k 2n | nl | sort -k 2n | cut -f1

... nó có một hành vi hơi khác trong trường hợp trùng lặp:

 nl x | sort  -k 2n | nl | sort -k 2n | cut -f1,3
 5  17 
 7  94 
 1  3 
 6  52 
 2  4 
 3  4 
 4  9

Vui lòng xem điểm chuẩn xếp hạng trung bình của Google trong cơ thể. Có lẽ, nó có thể đơn giản hóa đề xuất của bạn. Để có thể đặt vị trí tập dữ liệu bị sai lệch và / hoặc không thiên vị sẽ là tuyệt vời.
Léo Léopold Hertz

1
@masi, trùng lặp appart, bạn sẽ có được thứ hạng của Google nếu bạn chỉ sắp xếp theo thứ tự ngược lại:nl x | sort -k 2rn | nl | sort -k 2n | cut -f1,3
JJoao

6

Chỉ với GNU awk:

awk '
    FNR == NR {numbers[$1]=1; next} 
    FNR == 1 {
        n = asorti(numbers, sorted, "@ind_num_asc")
        for (i=1; i<=n; i++) rank[sorted[i]] = i
    }
    {print rank[$1]}
' file file

2
Lưu ý rằng numbers[$1]=1có thể được đơn giản hóa giống numbers[$1]như bạn không quan tâm đến các giá trị của hàm băm đó.
Stéphane Chazelas

3
Tôi thấy điều đó quá mơ hồ đối với thị hiếu của tôi và thích một nhiệm vụ để tạo thành phần mảng.
glenn jackman

1
@masi, "google xếp hạng trung bình" được cấy như thế nào? Tôi hoàn toàn nghi ngờ rằng nó sẽ không đơn giản hóa mã của tôi chút nào
glenn jackman

Mặt khác, tôi đã tự hỏi tầm quan trọng của việc gán giá trị 1 cho mảng là gì. Đối với tôi, h[key]là thành ngữ của việc gán khóa của hàm băm, trong khi đó a[key]=1sẽ là thành ngữ của việc đưa ra một giá trị thực cho phần tử băm của khóa đó .
Stéphane Chazelas
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.