2017-11-10 24 views
5

(Điều này được lấy cảm hứng từ một câu hỏi khác được đánh dấu là duplicate. Tôi nghĩ rằng đó là một vấn đề thú vị, mặc dù có lẽ là một giải pháp dễ dàng từ tổ hợp, mà tôi rất dốt nát .)Phương pháp phân chia toàn bộ vectơ thành từng cặp trong R

vấn đề

Đối với một vector có độ dài n, nơi n mod 2 là zero, tìm mọi cách có thể để phân vùng tất cả các yếu tố của véc tơ vào cặp, mà không cần thay thế, nơi trật tự không quan trọng.

Ví dụ, đối với một vector c(1,2,3,4):

list(c(1,2), c(3,4)) 
list(c(1,3), c(2,4)) 
list(c(1,4), c(2,3)) 

cách tiếp cận của tôi đã được như sau (xin lỗi trước cho mã mới):

# write a function that recursively breaks down a list of unique pairs (generated with combn). The natural ordering produced by combn means that for the first pass through, we take as the starting pair, all pairings with element 1 of the vector with all other elements. After that has been allocated, we iterate through the first p/2 pairs (this avoids duplicating). 

pairer2 <- function(kn, pair_list) { 

    pair1_partners <- lapply(kn, function(x) { 

    # remove any pairs in the 'master list' that contain elements of the starting pair. 
    partners <- Filter(function(t) !any(t %in% x), pair_list) 

    if(length(partners) > 1) { 

    # run the function again 
     pairer2(kn = partners[1:(length(partners)/2)], partners) 
    } else {return(partners)} 
    }) 

    # accumulate results into a nested list structure 
    return(mapply(function(x,y) {list(root = x, partners = y)}, kn, pair1_partners, SIMPLIFY = F)) 
} 

# this function generates all possible unique pairs for a vector of length k as the starting point, then runs the pairing off function above 

pair_combn <- function(k, n = 2) { 

    p <- combn(k, n, simplify = F) 

    pairer2(kn = p[1:(length(k)-1)], p)} 


# so far a vector k = 4 
pair_combn(1:4) 

[[1]] 
[[1]]$root 
[1] 1 2 

[[1]]$partners 
[[1]]$partners[[1]] 
[1] 3 4 



[[2]] 
[[2]]$root 
[1] 1 3 

[[2]]$partners 
[[2]]$partners[[1]] 
[1] 2 4 



[[3]] 
[[3]]$root 
[1] 1 4 

[[3]]$partners 
[[3]]$partners[[1]] 
[1] 2 3 

Nó cũng làm việc cho lớn hơn k như xa như Tôi có thể kể. Đây không phải là hiệu quả, có thể bởi vì Filter là chậm cho danh sách lớn, và tôi phải thú nhận tôi không thể thu gọn danh sách lồng nhau (đó là một đại diện cây của các giải pháp có thể) vào danh sách của mỗi phân vùng. Nó cảm thấy như có nên là một giải pháp thanh lịch hơn (trong R)?

Hãy nhớ rằng cách tiếp cận đệ quy này tạo ra một đại diện phân tích (mặc dù bất tiện) về các giải pháp khả thi.

Trả lời

1

Dưới đây là một cách:

> x <- c(1,2,3,4) 
> xc <- combn(as.data.frame(combn(x, 2)), 2, simplify = FALSE) 
> Filter(function(x) all(1:4 %in% unlist(x)), xc) 
[[1]] 
    V1 V6 
1 1 3 
2 2 4 

[[2]] 
    V2 V5 
1 1 2 
2 3 4 

[[3]] 
    V3 V4 
1 1 2 
2 4 3 

> 

Tổng quát hơn:

pair_combn <- function(x) { 
    Filter(function(e) all(unique(x) %in% unlist(e)), 
      combn(as.data.frame(combn(x, 2)), 
       length(x)/2, simplify = FALSE)) 
} 
+0

Đây là một mẹo nhỏ gọn. – gatsky

+0

Tôi không chắc tại sao một data.frame là đầu vào hợp lệ cho 'combn'. Phương pháp này không thành công ngay lập tức với lỗi cho vectơ có độ dài 14 đối với tôi (R 3.4.0, Windows). – gatsky

1

Thank để tiếp tục vấn đề của tôi (đánh dấu là trùng lặp đối với một số lý do kỳ lạ). Tôi nghĩ rằng không có giải pháp hoạt động tốt cho k> = 10. Gatsky của câu trả lời không làm việc cho tôi cho k = 6 (nó trả về 5 khả năng khi thực sự có 15). Giải pháp của Ista không thành công tại k = 12.

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