दिलचस्प पोस्ट
एंड्रॉइड सूचीदृश्य: दृश्यमान वस्तु का डेटा सूचकांक प्राप्त करें JQuery के साथ JSON ट्री खोज कैसे करें एचटीएमएल 5 वीडियो टैग के साथ स्थानीय (हार्ड ड्राइव) वीडियो फाइल खेलें? कोणीय 2 @ViewChild एनोटेशन रिटर्न अनिर्धारित दो सरणियों के बीच अंतर UITableView एकाधिक चयन साथ ही एक सूची में कई डेटा.फ्रेमों को मर्ज कर सकते हैं लंबे स्ट्रिंग से ईमेल पता कैसे प्राप्त करें क्या आप सीएसएस के साथ <br /> को लक्षित कर सकते हैं? पता लगाना है कि क्या आईफोन एक अंधेरे कमरे में है Windows बैच फ़ाइलें: .bat बनाम। सीएमडी? $ IonicView.enter और कैश में अंतर क्या है: गलत जावा में डिफ़ॉल्ट एक्सेस मॉडिफायर क्या है? जावास्क्रिप्ट ऑब्जेक्ट की प्रिंट सामग्री? फ़्लोटिंग प्वाइंट डिवाइडर हार्डवेयर कार्यान्वयन विवरण

नियमित, लगातार अनुक्रमों के समूहों में एक वेक्टर को कैसे विभाजित किया जाए?

मेरे पास एक सदिश है, जैसे कि c(1, 3, 4, 5, 9, 10, 17, 29, 30) और मैं एक साथ 'पड़ोसी' तत्वों को एक साथ समूह करना चाहता हूं जो एक नियमित, सख़्त सदिश में लगातार अनुक्रम बनाते हैं जिसके परिणामस्वरूप:

एल 1: 1
L2: 3,4,5
एल 3: 9, 10
एल 4: 17
एल 5: 29,30

निष्पक्ष कोड (एक पूर्व सी प्रोग्रामर का):

 partition.neighbors <- function(v) { result <<- list() #jagged array currentList <<- v[1] #current series for(i in 2:length(v)) { if(v[i] - v [i-1] == 1) { currentList <<- c(currentList, v[i]) } else { result <<- c(result, list(currentList)) currentList <<- v[i] #next series } } return(result) } 

अब मैं समझता हूं कि

ए) आर सी नहीं है (घुंघराले ब्रैकेट के बावजूद)
बी) वैश्विक चर शुद्ध बुराई हैं
ग) यह परिणाम प्राप्त करने का एक बहुत ही अकुशल तरीका है

, इसलिए किसी भी बेहतर समाधान का स्वागत है

वेब के समाधान से एकत्रित समाधान "नियमित, लगातार अनुक्रमों के समूहों में एक वेक्टर को कैसे विभाजित किया जाए?"

कुछ आर मुहावरों का भारी उपयोग करना:

 > split(v, cumsum(c(1, diff(v) != 1))) $`1` [1] 1 $`2` [1] 3 4 5 $`3` [1] 9 10 $`4` [1] 17 $`5` [1] 29 30 

डार्कोज़िग लिखते हैं, "आप अलग-अलग आधार पर एक बहुत नीपर कोड लिख सकते हैं …"

यहां एक तरीका है:

 split(v, cumsum(diff(c(-Inf, v)) != 1)) 

संपादित करें (जोड़ा गया समय):

टॉमी ने यह पता लगाया कि यह प्रकार के साथ सावधान रहकर तेजी से हो सकता है; इसका कारण यह तेजी से बढ़ता है कि split पूर्णांक पर तेजी से होता है, और वास्तव में अभी भी कारकों पर तेजी से बढ़ रहा है।

यहां यहोशू के समाधान हैं; cumsum से परिणाम एक संख्यात्मक है क्योंकि यह 1 साथ c घ है, इसलिए यह सबसे धीमा है।

 system.time({ a <- cumsum(c(1, diff(v) != 1)) split(v, a) }) # user system elapsed # 1.839 0.004 1.848 

बस 1L साथ 1L इसलिए परिणाम एक पूर्णांक गति काफी ऊपर है

 system.time({ a <- cumsum(c(1L, diff(v) != 1)) split(v, a) }) # user system elapsed # 0.744 0.000 0.746 

संदर्भ के लिए यह टॉमी का समाधान है; यह भी एक पूर्णांक पर विभाजित है

 > system.time({ a <- cumsum(c(TRUE, diff(v) != 1L)) split(v, a) }) # user system elapsed # 0.742 0.000 0.746 

यहाँ मेरा मूल समाधान है; यह भी एक पूर्णांक पर विभाजित है

 system.time({ a <- cumsum(diff(c(-Inf, v)) != 1) split(v, a) }) # user system elapsed # 0.750 0.000 0.754 

यहां पर यहोशू का परिणाम है, जिसके फलस्वरूप परिणाम split होने से पहले पूर्णांक में परिवर्तित split

 system.time({ a <- cumsum(c(1, diff(v) != 1)) a <- as.integer(a) split(v, a) }) # user system elapsed # 0.736 0.002 0.740 

पूर्णांक वेक्टर पर split सभी संस्करण उसी के समान हैं; यह भी तेज हो सकता है कि पूर्णांक वेक्टर पहले से ही एक कारक था, क्योंकि पूर्णांक से फर्क करने के लिए वास्तव में लगभग आधा समय लगता है। यहां मैं इसे सीधे एक कारक में बना देता हूं; यह सामान्य रूप में अनुशंसित नहीं है क्योंकि यह कारक वर्ग की संरचना पर निर्भर करता है। यह सिर्फ तुलनात्मक प्रयोजनों के लिए किया गया है

 system.time({ a <- cumsum(c(1L, diff(v) != 1)) a <- structure(a, class = "factor", levels = 1L:a[length(a)]) split(v,a) }) # user system elapsed # 0.356 0.000 0.357 

यहोशू और हारून पर मौजूद थे हालांकि, उनके कोड को सही प्रकार, पूर्णांक और तार्किकों के सावधान उपयोग से दो बार तेज़ी से अधिक बनाया जा सकता है:

 split(v, cumsum(c(TRUE, diff(v) != 1L))) v <- rep(c(1:5, 19), len = 1e6) # Huge vector... system.time( split(v, cumsum(c(1, diff(v) != 1))) ) # Joshua's code # user system elapsed # 2.64 0.00 2.64 system.time( split(v, cumsum(c(TRUE, diff(v) != 1L))) ) # Modified code # user system elapsed # 1.09 0.00 1.12 

आप एक data.frame बना सकते हैं और तत्वों को diff , ifelse और cumsum का उपयोग करके समूहों को असाइन कर सकते हैं, तो कुल मिलाकर उपयोग कर tapply :

 v.df <- data.frame(v = v) v.df$group <- cumsum(ifelse(c(1, diff(v) - 1), 1, 0)) tapply(v.df$v, v.df$group, function(x) x) $`1` [1] 1 $`2` [1] 3 4 5 $`3` [1] 9 10 $`4` [1] 17 $`5` [1] 29 30 

आप कट-अंक आसानी से परिभाषित कर सकते हैं:

 which(diff(v) != 1) 

उस प्रयास के आधार पर:

 v <- c(1,3,4,5,9,10,17,29,30) cutpoints <- c(0, which(diff(v) != 1), length(v)) ragged.vector <- vector("list", length(cutpoints)-1) for (i in 2:length(cutpoints)) ragged.vector[[i-1]] <- v[(cutpoints[i-1]+1):cutpoints[i]] 

जिसके परिणामस्वरूप:

 > ragged.vector [[1]] [1] 1 [[2]] [1] 3 4 5 [[3]] [1] 9 10 [[4]] [1] 17 [[5]] [1] 29 30 

यह एल्गोरिदम एक अच्छा नहीं है, लेकिन आप diff के आधार पर एक बहुत नीपर कोड लिख सकते हैं 🙂 गुड लक!