2012-07-12 8 views
19

कोड के इस ब्लॉक से पहले निर्धारित:विभाजन में एक संग्रह "K" पास करने के लिए बराबर टुकड़ों (स्काला, लेकिन नास्तिक भाषा)

  • dataset हो सकता है एक Vector या List
  • numberOfSlices एक Int है डेटासेट

मैं डेटासेट को numberOfSlices स्लाइस में विभाजित करना चाहता हूं, जितना संभव हो उतना वितरित करना चाहता हूं। "विभाजन" से मेरा अनुमान है कि मेरा मतलब है "विभाजन" (सभी का चौराहे खाली होना चाहिए, सभी का संघ मूल होना चाहिए) सेट सिद्धांत शब्द का उपयोग करने के लिए, हालांकि यह आवश्यक रूप से एक सेट नहीं है, केवल एक मनमाना संग्रह है।

उदा

dataset = List(1, 2, 3, 4, 5, 6, 7) 
numberOfSlices = 3 
slices == ListBuffer(Vector(1, 2), Vector(3, 4), Vector(5, 6, 7)) 

क्या मेरे पास नीचे की तुलना में ऐसा करने का एक बेहतर तरीका है? (जो मुझे भी यकीन नहीं है इष्टतम है ...) या शायद यह एक एल्गोरिदमिक व्यवहार्य प्रयास नहीं है, इस मामले में किसी भी ज्ञात अच्छी हेरिस्टिक?

val slices = new ListBuffer[Vector[Int]] 
val stepSize = dataset.length/numberOfSlices 
var currentStep = 0 
var looper = 0 
while (looper != numberOfSlices) { 
    if (looper != numberOfSlices - 1) { 
    slices += dataset.slice(currentStep, currentStep + stepSize) 
    currentStep += stepSize 
    } else { 
    slices += dataset.slice(currentStep, dataset.length) 
    } 
    looper += 1 
} 
+2

मुझे यकीन नहीं है कि "जितना संभव हो उतना वितरित" की व्याख्या कैसे करें। आपके कोड पर जाकर, 'सेक: समूहीकृत (Int)' पहले से ही जो भी आप चाहते हैं वह करता है, सिवाय इसके कि यह टुकड़ा आकार से ऊपर कभी नहीं जाता है। – Kaito

+3

ऐसा लगता है कि 'समूहित' इसे "x" के समूहों में विभाजित करेगा जबकि मैं संग्रह को "x" समूहों में विभाजित करना चाहता हूं। मैंने जवाब में यह कोशिश की, 'सूची (1, 2, 3, 4, 5)। समूहित (2)। टोस्ट' सूची देता है (सूची (1, 2), सूची (3, 4), सूची (5)) 'जबकि मुझे कुछ सूची चाहिए (सूची (1, 2), सूची (3, 4, 5)) '। – adelbertc

उत्तर

12

xs.grouped(xs.size/n) के व्यवहार आप के लिए काम नहीं करता है, यह वास्तव में आप क्या चाहते हैं परिभाषित करने के लिए बहुत आसान है। भागफल छोटे टुकड़ों के आकार है, और शेष बड़ा टुकड़े की संख्या है:

def cut[A](xs: Seq[A], n: Int) = { 
    val (quot, rem) = (xs.size/n, xs.size % n) 
    val (smaller, bigger) = xs.splitAt(xs.size - rem * (quot + 1)) 
    smaller.grouped(quot) ++ bigger.grouped(quot + 1) 
} 
+1

यह अच्छा है लेकिन दुर्भाग्यवश 'यथासंभव समान रूप से वितरित' की निर्दिष्ट आवश्यकता को बढ़ाता है, क्योंकि सभी 'बड़े' सेगमेंट अंतिम होते हैं - उदाहरण के लिए, 'कट (1 से 15, 10) .toList.map (_। आकार) '5 एक-तत्व खंडों के बाद 5 दो-तत्व खंड उत्पन्न करता है। –

0

Kaito के रूप में उल्लेख है grouped आप के लिए वास्तव में क्या देख रहे है। लेकिन अगर आप जानना चाहते हैं कि इस तरह की विधि को कैसे कार्यान्वित किया जाए, तो कई तरीके हैं ;-)। उदाहरण के लिए आप इसे इस तरह कर सकता है:

def grouped[A](xs: List[A], size: Int) = { 
    def grouped[A](xs: List[A], size: Int, result: List[List[A]]): List[List[A]] = { 
    if(xs.isEmpty) { 
     result 
    } else { 
     val (slice, rest) = xs.splitAt(size) 
     grouped(rest, size, result :+ slice) 
    } 
    } 
    grouped(xs, size, Nil) 
} 
+0

'समूहित' आकार जितना संभव हो उतना आकार नहीं बनाता है, अंतिम उप-सूची दूसरों की तुलना में बहुत छोटी हो सकती है। – dividebyzero

0

मैं इसे इस तरह के दृष्टिकोण चाहते हैं:, यह देखते हुए n तत्वों और m विभाजन (एन> मीटर) या तो n mod m == 0 किस स्थिति में, प्रत्येक विभाजन में n/m तत्व होंगे, या n mod m = y, इस मामले में आपके पास n/m तत्वों के साथ प्रत्येक विभाजन होगा और आपको पर y वितरित करना होगा।

आपके पास y स्लॉट n/m+1 तत्वों और (एम-वाई) स्लॉट एन/एम के साथ होंगे। आप उन्हें कैसे वितरित करते हैं आपकी पसंद है।

6

ठेठ "इष्टतम" विभाजन काटने के बाद एक सटीक आंशिक लंबाई की गणना करता है और फिर लेने के लिए वास्तविक संख्या को खोजने के लिए दौर: जो अक्सर अधिक है

def cut[A](xs: Seq[A], n: Int):Vector[Seq[A]] = { 
    val m = xs.length 
    val targets = (0 to n).map{x => math.round((x.toDouble*m)/n).toInt} 
    def snip(xs: Seq[A], ns: Seq[Int], got: Vector[Seq[A]]): Vector[Seq[A]] = { 
    if (ns.length<2) got 
    else { 
     val (i,j) = (ns.head, ns.tail.head) 
     snip(xs.drop(j-i), ns.tail, got :+ xs.take(j-i)) 
    } 
    } 
    snip(xs, targets, Vector.empty) 
} 

इस तरह आप अपने लंबे समय तक और कम ब्लॉक बीच-बीच में हो जाएगा, एकरूपता के लिए वांछनीय:

scala> cut(List(1,2,3,4,5,6,7,8,9,10),4) 
res5: Vector[Seq[Int]] = 
    Vector(List(1, 2, 3), List(4, 5), List(6, 7, 8), List(9, 10)) 

आप और भी अधिक बार कटौती कर सकते हैं की तुलना में आप तत्वों है:

scala> cut(List(1,2,3),5) 
res6: Vector[Seq[Int]] = 
    Vector(List(1), List(), List(2), List(), List(3)) 
2

यहां एक-लाइनर है जो मेरे लिए नौकरी करता है, एक रिकर्सिव फ़ंक्शन की परिचित स्कैला चाल का उपयोग करके Stream देता है। चंक आकार के चारों ओर (x+k/2)/k के उपयोग पर ध्यान दें, अंतिम सूची में छोटे और बड़े हिस्सों को घुमाएं, सभी आकारों के साथ अंतर के एक तत्व के साथ।यदि आप (x+k-1)/k के साथ इसके बजाय गोल करते हैं, तो आप छोटे ब्लॉक को अंत में ले जाते हैं, और x/k उन्हें शुरुआत में ले जाते हैं।

def k_folds(k: Int, vv: Seq[Int]): Stream[Seq[Int]] = 
    if (k > 1) 
     vv.take((vv.size+k/2)/k) +: k_folds(k-1, vv.drop((vv.size+k/2)/k)) 
    else 
     Stream(vv) 

डेमो:

scala> val indices = scala.util.Random.shuffle(1 to 39) 

scala> for (ff <- k_folds(7, indices)) println(ff) 
Vector(29, 8, 24, 14, 22, 2) 
Vector(28, 36, 27, 7, 25, 4) 
Vector(6, 26, 17, 13, 23) 
Vector(3, 35, 34, 9, 37, 32) 
Vector(33, 20, 31, 11, 16) 
Vector(19, 30, 21, 39, 5, 15) 
Vector(1, 38, 18, 10, 12) 

scala> for (ff <- k_folds(7, indices)) println(ff.size) 
6 
6 
5 
6 
5 
6 
5 

scala> for (ff <- indices.grouped((indices.size+7-1)/7)) println(ff) 
Vector(29, 8, 24, 14, 22, 2) 
Vector(28, 36, 27, 7, 25, 4) 
Vector(6, 26, 17, 13, 23, 3) 
Vector(35, 34, 9, 37, 32, 33) 
Vector(20, 31, 11, 16, 19, 30) 
Vector(21, 39, 5, 15, 1, 38) 
Vector(18, 10, 12) 

scala> for (ff <- indices.grouped((indices.size+7-1)/7)) println(ff.size) 
6 
6 
6 
6 
6 
6 
3 

सूचना कैसे grouped सभी उप-सूचियों के आकार बाहर भी करने की कोशिश नहीं करता।

+0

प्रतीक को हल नहीं कर सकता है '# :: ' – Vasily802

+0

प्रतीक' फ़ोल्डर्स ' – Vasily802

+1

@ Vasily802 को हल नहीं कर सकता मैं नहीं जानता कि क्यों' # :: 'काम नहीं किया हो सकता है, लेकिन मैंने इसे बदल दिया है और कोड को थोड़ा सुधार भी किया है, और निश्चित डेमो धन्यवाद... – dividebyzero

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