2012-10-09 42 views
5

Tôi có nhu cầu về chức năng giống như băm trong Matlab, trong đó bản đồ băm sao chép vectơ sang vec-tơ khác và số lượng vectơ (trong hàng trăm nghìn) không được biết trước.Phát triển Hashmap của vectơ trong Matlab

Tôi đã cố gắng của Matlab sẵn có Containers.Map, nhưng điều đó không chấp nhận vectơ làm khóa. Sau đó, tôi đã thử java.util.HashMap:

>> map = java.util.HashMap; 
>> map.put(1:3,zeros(2,1)); 
>> map.get(1:3) 

ans = 

[] 

Vì một lý do nào đó dường như không hoạt động, mặc dù HashMap của Java có thể ánh xạ mảng thành mảng.

Tùy chọn khác sẽ là giữ hai ma trận riêng biệt, một cho các khóa và một cho các giá trị và tăng dần chúng. Nhưng tôi không muốn thực sự muốn làm điều đó vì nỗi đau trong Matlab ngày càng tăng dần (thậm chí với số lượng gia tăng khối vv, ví dụ: here).

Câu hỏi: 1. Tại sao HashMap của Java không hoạt động ở đây? 2. Bất kỳ cách tiếp cận nào khác?

Cảm ơn.

+2

xem http://stackoverflow.com/questions/1352553/how-can-i-use-matlab-arrays-as-keys-to-the-hashmap-java-objects – Rasman

+1

Phạm vi giá trị trong vectơ chính? Nếu chúng ints dưới 2^16, bạn chỉ có thể chuyển đổi chúng thành 'char' và sử dụng các chuỗi vui nhộn như các phím. –

+0

Cảm ơn tất cả các câu trả lời của bạn. Các vectơ chính thực sự là ints dưới 2^16 vì vậy tôi so sánh bằng cách sử dụng các thùng chứa.Bản đồ với các phím char và HashMap của java với các phím tương tự như bài Rasman liên kết tới: ok, đó là quá nhiều mã để đăng ở đây vì vậy tôi sẽ đăng nó như một câu trả lời. – Matt

Trả lời

4

Đây là một kludge thực hiện những gì bạn muốn. . .

map = java.util.HashMap;  
key = java.util.Vector; 

matKey = 1:3; 
for nn=1:numel(matKey) 
    key.add(matKey(nn)); 
end 

map.put(key,zeros(2,1)); 
map.get(key) 

..nó là điểm bắt đầu.

+1

Điều này có thể hoạt động và tốt hơn là "kludge", nhưng bạn phải cẩn thận - nó hơi gian lận một chút bằng cách tái sử dụng đối tượng Java trong 'key', khi tôi nghĩ OP muốn có thể kéo các mục ra giá trị. Mã OP không hoạt động vì Matlab '1: 3' được chuyển thành một mảng đôi nguyên thủy Java, có các ngữ nghĩa đẳng thức. Ví dụ đầu tiên của bạn sẽ hoạt động nếu bạn kết thúc với một Vector đôi, mà sẽ có ngữ nghĩa bằng giá trị. Không chắc chắn chuyển đổi sẽ như thế nào; bạn có thể cần ép buộc nó bằng cách thực hiện 'key.add (java.lang.Double (matKey (nn)));'. –

+1

Ví dụ thứ hai có thể sẽ không hoạt động - 'key.add (1: 3)' kết thúc bằng Vector dài gấp đôi [], kết thúc bằng tính bình đẳng theo danh tính. Tôi không nghĩ rằng bạn sẽ có thể kéo giá trị trở lại bằng cách sử dụng một '1: 3' khác; bạn cần đối tượng 'key' gốc. Ví dụ. nếu bạn làm 'key2 = java.util.Vector; key2.add (1: 3); map.get (key2) ', nó có lấy giá trị không? Bởi vì tôi nghĩ đó là những gì OP cần cho nó hoạt động. –

+0

@AndrewJanke bạn đã chính xác. Sau khi thử nghiệm, Kludge 2 đã không thực sự hoạt động. Đã xóa – learnvst

1

Tôi đã so sánh các thùng chứa.Map với các phím char (nhờ Andrew Janke) tới java.util.HashMap với một đối tượng bao bọc làm khóa (như trong this post, cũng nhờ Andrew Janke và nhờ Rasman đã chỉ ra) :

numvec = 10^5; 
S = round(rand(numvec,10)*40); 

matmap = containers.Map(); 
%pick a random vector 
idx = ceil(rand()*numvec); 
s1 = S(idx,:); 

%put it in the map 
matmap(char(s1)) = zeros(1,4); 
for i=1:5*10^5 

    if i==10^3 tic; end %allow some time for getting up to speed before timing 

    %pick a random vector and put it in the map 
    idx = ceil(rand()*numvec); 
    s2 = S(idx,:); 
    matmap(char(s2)) = zeros(1,4); 

    %retrieve value of previous vector 
    v = matmap(char(s1)); 

    %modify it randomly and put it back 
    v(ceil(rand()*4)) = rand(); 
    matmap(char(s1)) = v; 

    s1 = s2; 
end 
toc 

javaaddpath('/Test/bin'); 
import test.ArrayKey; 
javmap = java.util.HashMap; 

idx = ceil(rand()*numvec); 
s1 = S(idx,:); 

%also convert value to ArrayKey so we can retrieve it by ref -- saves a put 
%operation 
javmap.put(ArrayKey(s1), ArrayKey(zeros(1,4))); 
for i=1:5*10^5 

    if i==10^3 tic; end 

    idx = ceil(rand()*numvec); 
    s2 = S(idx,:); 
    javmap.put(ArrayKey(s2), ArrayKey(zeros(1,4))); 
    v = javmap.get(ArrayKey(s1)); 
    v.x(ceil(rand()*4)) = rand(); 
    s1 = s2; 
end 
toc 

Kết quả:

>> testmaps 
Elapsed time is 58.600282 seconds. 
Elapsed time is 97.617556 seconds. 

containers.Map là người chiến thắng.


Chỉnh sửa: Tôi kiểm tra lại numvec = 10^6 và mọi thứ khác giống nhau. Cách tiếp cận container.Map chạy trong 59 giây. Cách tiếp cận HashMap không hoàn thành sau 5 phút và khiến Matlab trở nên không phản hồi.


Chỉnh sửa2: Tôi cũng đã thử phân bổ trước hai ma trận riêng biệt và tìm khóa bằng cách sử dụng ismember. Hiệu suất kém hơn HashMap.

+0

Tuyệt. Có nghĩa là container.Map hoạt động tốt hơn: có phí trên mỗi cuộc gọi Java từ mã M và chuyển đổi khóa sử dụng nhiều cuộc gọi, tăng theo độ dài khóa. –

0

Gần đây tôi đã phải đối phó với một vấn đề tương tự, không phải với vectơ mà là với mảng.

Matlab có hàm mat2str chức năng chuyển đổi ma trận thành chuỗi. Nếu bạn không cần các vectơ để phát triển động trong HashMap, bạn có thể biểu diễn vectơ dưới dạng một chuỗi và sử dụng nó làm khóa/giá trị của bạn. Trong một số trường hợp, điều này có lẽ không phải là rất hữu ích, nhưng nó là một giải pháp nhanh chóng và bẩn nếu mọi thứ là tĩnh.

Các vấn đề liên quan