2017-11-16 37 views
13

मैं एक सूचीआम तत्वों के साथ विलय सूची

[[1]] 
[1] 7 

[[2]] 
[1] 10 11 12 211 446 469 

[[3]] 
[1] 10 11 12 13 

[[4]] 
[1] 11 12 13 215 

[[5]] 
[1] 15 16 

[[6]] 
[1] 15 17 216 225 

मैं सूची स्लाइस आम तत्व है कि मर्ज करना चाहते हैं, और सूचकांक जो स्लाइस सूची मिला दिया गया है। मेरा वांछित आउटपुट नीचे है।

$`1` 
[1] 7 

$`2`, `3`, `4` 
[1] 10 11 12 13 211 215 446 469 

$`5`,`6` 
[1] 15 16 17 216 225 

(मैं नई सूची के नाम के रूप में मूल सूची टुकड़ा सूचकांकों की है, लेकिन उत्पादन के किसी भी रूप ठीक है।)

प्रतिलिपि प्रस्तुत करने योग्य डेटा:

mylist <- list(7, c(10, 11, 12, 211, 446, 469), c(10, 11, 12, 13), c(11, 
12, 13, 215), c(15, 16), c(15, 17, 216, 225)) 
+0

यह 'igraph' पैकेज के लिए एक अच्छा उपयोग केस हो सकता है। –

उत्तर

10

समाधान के साथ खुश नहीं लेकिन मुझे लगता है कि जवाब देता है।

unique(sapply(lst, function(x) 
     unique(unlist(lst[sapply(lst, function(y) 
         any(x %in% y))])))) 


#[[1]] 
#[1] 7 

#[[2]] 
#[1] 10 11 12 211 446 469 13 215 

#[[3]] 
#[1] 15 16 17 216 225 

यह अगर सूची तत्व के किसी भी किसी भी एक और सूची में मौजूद है की जाँच करने के मूल रूप से डबल पाश है: वहाँ अब भी सुधार की गुंजाइश है। यदि आपको ऐसा कोई तत्व मिलता है तो उनमें से केवल unique मानों को ले कर उन्हें मिलाएं।

डेटा

lst <- list(7, c(10 ,11 ,12, 211, 446, 469), c(10, 11, 12, 13),c(11 ,12, 13 ,215), 
       c(15, 16), c(15, 17 ,216 ,225)) 
0

यहाँ एक पुनरावर्ती क्रिया उस कार्य को पूरा करता है (हालांकि अभी यह चेतावनी के एक झुंड उत्पन्न करता है) है।

mylist <- list(7, c(10, 11, 12, 211, 446, 469), c(10, 11, 12, 13), c(11, 12, 13, 215), c(15, 16), c(15, 17, 216, 225)) 

commonElements = function(l,o=list(l[[1]])){ 
    if(length(l) == 0){return(o)} 
    match = which(unlist(lapply(lapply(o,intersect,l[[1]]),any))) 
    if(length(match) == 0) o[[length(o)+1]] = l[[1]] 
    if(length(match) == 1) o[[match]] = unique(c(o[[match]],l[[1]])) 
    if(length(match) > 1){ 
    o[[match[1]]] = unique(unlist(o[match])) 
    p[rev(match)[-1]] = NULL 
    } 
    l[[1]] = NULL 
    commonElements(l,o) 
} 

commonElements(mylist) 

मूल रूप से, एक सूची में गुजरती हैं और उत्पादन, o, l के पहले तत्व के साथ का दृष्टांत। फिर में प्रत्येक समूह के खिलाफ l के प्रत्येक मान की जांच करें, यदि यह कुछ भी मेल नहीं खाता है, तो o में नया तत्व बनाएं, यदि यह एक से मेल खाता है, तो अद्वितीय सेट रखें और यदि यह 1 से अधिक से मेल खाता है, तो o में समूहों को संयोजित करें और अतिरिक्त ड्रॉप करें ।

6

"मैट्रिक्स" और "igraph" पैकेज का उपयोग करके एक और तरीका है।

सबसे पहले, हमें कौन से तत्व जुड़े हुए हैं, इस बारे में जानकारी निकालने की आवश्यकता है।

library(Matrix) 
i = rep(1:length(mylist), lengths(mylist)) 
j = factor(unlist(mylist)) 
tab = sparseMatrix(i = i, j = as.integer(j), x = TRUE, dimnames = list(NULL, levels(j))) 
#as.matrix(tab) ## just to print colnames 
#   7 10 11 12 13 15 16 17 211 215 216 225 446 469 
#[1,] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
#[2,] FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE TRUE 
#[3,] FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
#[4,] FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE 
#[5,] FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
#[6,] FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE TRUE FALSE FALSE 

पता करें कि प्रत्येक तत्व एक दूसरे से जुड़ा हुआ है: विरल मैट्रिक्स का उपयोग करना, potetially, एक बहुत स्मृति के उपयोग को बचा सकता है

connects = tcrossprod(tab, boolArith = TRUE) 
#connects 
#6 x 6 sparse Matrix of class "lsCMatrix" 
#     
#[1,] | . . . . . 
#[2,] . | | | . . 
#[3,] . | | | . . 
#[4,] . | | | . . 
#[5,] . . . . | | 
#[6,] . . . . | | 

फिर, रेखांकन का उपयोग कर, हम समूह कर सकते हैं "MyList के सूचकांकों ":

library(igraph) 
# 'graph_from_adjacency_matrix' seems to not work with the "connects" object directly. 
# An alternative to coercing "connects" here would be to build it as 'tcrossprod(tab) > 0' 

group = clusters(graph_from_adjacency_matrix(as(connects, "lsCMatrix")))$membership 
#group 
#[1] 1 2 2 2 3 3 

और अंत में, श्रेणीबद्ध:

tapply(mylist, group, function(x) sort(unique(unlist(x)))) 
#$`1` 
#[1] 7 
# 
#$`2` 
#[1] 10 11 12 13 211 215 446 469 
# 
#$`3` 
#[1] 15 16 17 216 225 

tapply(1:length(mylist), group, toString) 
#  1   2   3 
#  "1" "2, 3, 4" "5, 6" 
0

यहाँ एक purrr आधारित दृष्टिकोण है:

library(purrr) 

mylist <- list(7, 
       c(10, 11, 12, 211, 446, 469), 
       c(10, 11, 12, 13), 
       c(11, 12, 13, 215), 
       c(15, 16), 
       c(15, 17, 216, 225)) 

result <- mylist %>% 
    # check whether any numbers of an element are in any of the elements 
    map(~map_lgl(mylist, compose(any, `%in%`), .x)) %>% 
    unique() %>% # drop duplicated groups 
    map(~reduce(mylist[.x], union)) # subset lst by group and collapse subgroups 

str(result) 
#> List of 3 
#> $ : num 7 
#> $ : num [1:8] 10 11 12 211 446 469 13 215 
#> $ : num [1:5] 15 16 17 216 225 

तर्क यहां रौनक के जवाब के समान है; मुझे बस पढ़ने के लिए यह आसान लगता है। यदि आप चाहें, तो आप अंतिम पंक्ति map(~unique(flatten_dbl(mylist[.x]))) के रूप में लिख सकते हैं या इसे map(~mylist[.x]) %>% simplify_all() %>% map(unique) में विभाजित कर सकते हैं।

सूचकांक जिनमें से तत्व है जो समूह, बस तत्वों subsetting के लिए इस्तेमाल किया पर which कॉल करने के लिए एकत्रित किया गया है के लिए:

mylist %>% 
    map(~map_lgl(mylist, compose(any, `%in%`), .x)) %>% 
    unique() %>% 
    map(which) %>% 
    str() 
#> List of 3 
#> $ : int 1 
#> $ : int [1:3] 2 3 4 
#> $ : int [1:2] 5 6 

पूरी बात के लिए एक वैकल्पिक तर्क है सूची के बजाय नेस्ट करना के लिए कॉल, स्वयं में शामिल होने का मतलब है जो सामने (cross2 के साथ) ऊपर है, वहाँ कोई subsetting बाद में है, और कार्यों का सबसे बस संचालन सेट कर रहे हैं:

mylist %>% 
    map(cross2, mylist) %>% 
    modify_depth(2, reduce, ~if(length(intersect(.x, .y)) > 0) sort(union(.x, .y))) %>% 
    map(reduce, union) %>% 
    unique() 

या 0 का उपयोग करके .filter पैरामीटर,

mylist %>% 
    map(cross2, mylist, ~length(intersect(.x, .y)) == 0) %>% 
    map(compose(sort, unique, unlist)) %>% 
    unique() 

जो

mylist %>% 
    map(function(element) sort(unique(unlist(cross2(element, mylist, ~length(intersect(.x, .y)) == 0))))) %>% 
    unique() 

को सघन किया जा सकता है इन तरीकों, हालांकि अंत तक डुप्लिकेट समूहों ड्रॉप नहीं है, इसलिए वे संभावना कम कुशल हो।

संबंधित मुद्दे