2012-07-12 1 views
19

パーティションのコードブロックの前に定義された「K」近いツー等分(スカラ、しかし依存しない言語)に収集

  • datasetVector又はList
  • numberOfSlicesすることができるIntありますスライスデータセットのスライス数を指定します。

データセットをできるだけ均等に分割して分割したいと考えています。 「分割」とは、必ずしも任意の集合ではないが、集合理論の用語を使用するためには、「分割」(すべての交差が空でなければならず、すべての結合が元のものでなければならない)を意味すると思う。

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

「できるだけ均等に配分する」と解釈する方法がわかりません。あなたのコードを見れば、 'Seq:grouped(Int)'は既にスライスサイズを上回っていないことを除いて、あなたが望むものを実行します。 – Kaito

+3

'' grouped'は "x"のグループに分けられますが、私はコレクションを "x"グループに分けたいと思います。リスト(1,2,3,4,5).grouped(2).toList'は 'List(1,2)、List(3,4)、List(5) ) '私は' List(List(1,2)、List(3、4、5)) 'のようなものを求めています。 – adelbertc

答えて

12

:あなたは、例えば可能性は、このようにそれを行います。商は、小片の大きさであり、そして残りが大きい個数である:n要素とmパーティション(N> M)が与えられ、いずれかの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

これは良いことですが、残念ながら、すべての '大きな'セグメントが最後に来るので、残念ながら 'できるだけ均等に分散されました'という前述の要件を引き継ぎます。たとえば、 'cut(1 to 15、10).toList.map(_。size) 'は5つの1要素セグメントの後に5つの2要素セグメントが続きます。 –

0

Kaitoは、あなたが探しているものと全く同じです。しかし、そのようなメソッドを実装する方法を知りたいだけなら、多くの方法があります;-)。 xs.grouped(xs.size/n)の行動は、それが正確に何をしたい定義するために非常に簡単です、あなたのために動作しない場合

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

'grouped'はサイズを可能な限り同じにしません。最後のサブリストは他のサブリストよりもずっと小さいかもしれません。 – dividebyzero

0

私はこのようにそれに近づくだろうmod m == 0の場合、各パーティションにはn/m要素があり、n mod m = yの場合は、n/m要素の各パーティションがあり、mにはyを配布する必要があります。

n/m+1の要素とn/mの(m-y)のスロットを持つyスロットがあります。それらをどのように配布するかはあなたの選択です。

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),5) 
res6: Vector[Seq[Int]] = 
    Vector(List(1), List(), List(2), List(), List(3)) 

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)) 

あなたも、あなたが要素を持っているよりも多くの時間を削減することができます210

2

ここには、私にとって仕事をしてくれる1つのライナーがあります。おなじみのScalaのトリックを使って、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

シンボル' folds'を解決できません – Vasily802

+1

@ Vasily802 '#::'はうまくいかなかったかもしれないが、私はそれを置き換えてコードを少し改善し、デモ。ありがとう... – dividebyzero

関連する問題