2015-09-01 12 views
5

Từ trang trợ giúp R ​​của trận đấu():Julia phiên bản của R's Match?

Mô tả:

‘match’ returns a vector of the positions of (first) matches of 
its first argument in its second. 

Đó là, tôi có thể cung cấp cho hai vectơ, trận đấu (v1, v2) trả về một vector mà các yếu tố i'th là chỉ mục trong đó v1 [i] xuất hiện trong v2.

Có chức năng tương tự như vậy đối với Julia không? Tôi không thể tìm thấy nó.

+1

http: // stackoverflow .com/questions/20102250/find-first-index-of-an-item-in-an-array-trong-julia – Khashaa

Trả lời

6

Có vẻ như bạn đang tìm kiếm indexin (cũng giống như thức ăn gia súc tìm kiếm, điều này được gọi là cũng ismember bởi Matlab). Nó hơi khác một chút: nó trả về một vectơ trong đó phần tử thứ i là chỉ số cuối cùng ở đó v1[i] xuất hiện trong v2.

julia> v1 = [8,6,7,11]; v2 = -10:10; 
     idxs = indexin(v1, v2) 
4-element Array{Int64,1}: 
19 
17 
18 
    0 

Nó trả về zero cho chỉ số của một phần tử trong v1 mà không xuất hiện trong v2. Vì vậy, bạn có thể "tái tạo" các bộ phận của v1 có trong v2 đơn giản bằng cách lập chỉ mục bởi các chỉ số khác không:

julia> v2[idxs[idxs .> 0]] 
3-element Array{Int64,1}: 
8 
6 
7 

Nếu bạn nhìn vào the implementation, bạn sẽ thấy rằng nó sử dụng một từ điển để lưu trữ và tìm kiếm các các chỉ số. Điều này có nghĩa là nó chỉ tạo một đường chuyền vượt qua v1v2 mỗi cái, thay vì tìm kiếm qua v2 cho mọi phần tử trong v1. Nó sẽ hiệu quả hơn nhiều trong hầu hết các trường hợp.

Nếu điều quan trọng là để phù hợp với hành vi R và trả lại chỉ số đầu tiên, chúng ta có thể cũi tắt việc thực hiện cơ sở và chỉ xây dựng từ điển ngược nên các chỉ số thấp hơn ghi đè lên những cái trở lên:

function firstindexin(a::AbstractArray, b::AbstractArray) 
    bdict = Dict{eltype(b), Int}() 
    for i=length(b):-1:1 
     bdict[b[i]] = i 
    end 
    [get(bdict, i, 0) for i in a] 
end 

julia> firstindexin([1,2,3,4], [1,1,2,2,3,3]) 
4-element Array{Int64,1}: 
1 
3 
5 
0 

julia> indexin([1,2,3,4], [1,1,2,2,3,3]) 
4-element Array{Int64,1}: 
2 
4 
6 
0 
+0

Câu trả lời hay, cảm ơn bạn :) – Lindon

4

Tôi không nghĩ rằng điều này tồn tại, nhưng nhận xét của @ Khashaa (và câu trả lời của Tim Holy cho câu hỏi khác) chỉ ra, bạn sẽ có thể đưa ra định nghĩa của mình khá nhanh. Một nỗ lực đầu tiên:

function matched(v1::Array, v2::Array) 
    matched = zeros(length(v1)) 
    for i = 1:length(v1) 
    matched[i] = findfirst(v2, v1[i]) 
    end 
    return matched 
end 

(lưu ý rằng tôi gọi là chức năng matchedmatch được định nghĩa trong cơ sở cho phù hợp với chuỗi, nếu bạn muốn mở rộng nó, bạn sẽ phải nhập khẩu Base.match đầu tiên). Bạn chắc chắn có thể làm điều này nhanh hơn khi áp dụng một số thủ thuật từ phần hiệu suất của tài liệu Julia nếu bạn quan tâm đến hiệu suất.
Chức năng này phải làm những gì bạn đang tìm kiếm nếu tôi hiểu chính xác, hãy thử nó với ví dụ:

v1 = [rand(1:10) for i = 1:100] 
v2 = [rand(1:10) for i = 1:100] 
matched2(v1,v2) 
Các vấn đề liên quan