Tôi có một nhóm khóa (ký tự) < -> liên kết băm (số nguyên) trong R. Tôi muốn lưu trữ các liên kết này trong một cấu trúc duy nhất cho phép tôi để tham khảo một cặp khóa/băm bằng khóa, và cũng bằng băm.Cấu trúc dữ liệu thích hợp cho khóa hai chiều <-> bảng tra cứu val
Vì vậy, một cái gì đó giống như
"hello" <-> 1234
trong biến db
.
Và truy cập nó với (ish; không phải là cú pháp truy cập chính xác này):
db["hello"] -> 1234
db[1234] -> "hello"
tôi đã cố gắng sử dụng một khung dữ liệu, và đặt tên cho các rownames các phím. Nhưng sau đó tôi không thể tham chiếu một hàng bằng số nguyên băm. Nếu tôi sử dụng số nguyên băm làm tên miền, thì tôi không thể tham chiếu bằng tên khóa, v.v.
Giải pháp hiện tại của tôi là giữ hai dbs dưới dạng hai khung dữ liệu. Một cái có băm tên là rownames, cái còn lại có các phím như rownames. Điều này làm việc, nhưng có vẻ hơi khó xử và lặp đi lặp lại để giữ khoảng hai khung dữ liệu giống hệt nhau (khác với tên của họ).
Tôi muốn nó siêu nhanh ở cả hai hướng :). Tôi nghĩ rằng điều này có nghĩa là O (log (n)) cho hướng ký tự, và O (1) cho hướng số nguyên, nhưng tôi không phải là một chuyên gia về cấu trúc/thuật toán dữ liệu. O (log (n)) theo hướng số nguyên có lẽ là OK, nhưng tôi nghĩ O (n) (cần phải đi qua toàn bộ giải pháp db) theo một trong hai hướng sẽ cân nhắc mọi thứ xuống quá nhiều.
db cũng là tính từ. Tức là, mỗi khóa ánh xạ chính xác một giá trị và mỗi giá trị ánh xạ chính xác đến một khóa.
EDIT: Cảm ơn bài viết cho đến nay:
Chạy một vài xét nghiệm, kỹ thuật trận đấu chắc chắn là chậm hơn so với một data.table có khóa. Như Martin đã chỉ ra, điều này là do thời gian cần thiết cho trận đấu để tạo ra bàn phím. Đó là, cả hai trận đấu và một data.table keyed thực hiện một tìm kiếm nhị phân để tìm giá trị. Nhưng bất kể, trận đấu quá chậm so với nhu cầu của tôi khi trả về một giá trị duy nhất. Vì vậy, tôi sẽ mã hóa một giải pháp data.table và đăng bài.
> system.time(match(1,x))
user system elapsed
0.742 0.054 0.792
> system.time(match(1,x))
user system elapsed
0.748 0.064 0.806
> system.time(match(1e7,x))
user system elapsed
0.747 0.067 0.808
> system.time(x.table[1])
user system elapsed
0 0 0
> system.time(x.table[1e7])
user system elapsed
0.001 0.001 0.000
> system.time(x.table[1e7])
user system elapsed
0.005 0.000 0.005
> system.time(x.table[1])
user system elapsed
0.001 0.000 0.000
> system.time(x.table[1])
user system elapsed
0.020 0.001 0.038
EDIT2:
tôi đã đi với các giải pháp fmatch và một vector được đặt tên. Tôi thích sự đơn giản của cách tiếp cận trận đấu, nhưng tôi đang thực hiện các lần tra cứu lặp lại trên db, do đó, hiệu suất truy cập của việc tạo lại bảng băm trên mỗi cuộc gọi để phù hợp là quá lớn.
fmatch có giao diện tương tự như đối sánh, hoạt động trên cùng một kiểu dữ liệu vectơ, v.v. Nó chỉ lưu trữ/ghi nhớ bảng băm được tạo để các cuộc gọi tiếp theo trên vectơ có tên chỉ thực hiện tra cứu băm. Tất cả điều này là trừu tượng từ người gọi, vì vậy fmatch chỉ đơn giản là một dropin cho phù hợp.
Simple mã wrapper cho việc tra cứu hai chiều:
cách tiếp cậngetChunkHashes = function(chunks, db) {
return(db[fmatch(chunks, names(db))])
}
getChunks = function(chunkHashes, db) {
return(names(db[fmatch(chunkHashes, db)]))
}
Có thể là tốt để thêm ghi chú về bất kỳ ràng buộc hiệu suất nào bạn có thể có (tức là nó phải siêu nhanh theo cả hai hướng ...?) – joran
Có lẽ [fastmatch] xuất sắc (http://cran.ma. imperial.ac.uk/web/packages/fastmatch/index.html) gói có thể giúp đỡ. –