3

シーケンスのシーケンスである型が与えられた場合、それを単一のフラット化されたシーケンス型に変換するにはどうすればよいですか? 次の Ceylon コードを検討してください。

Integer[] range(Integer max) {
    return [ for (idx in 1..max) idx ];
}

Integer[] prod(Integer max, Integer occurrences) {
    Integer[][] nestedSequence = [for (occurrence in 1..occurrences) range(max)];
    return // ??? something to produce a flattened sequence 
}

assert (prod(2, 2) == [1, 2, 1, 2]);

私は初めて Ceylon を試しており、チュートリアルと API ドキュメントを手探りで進めています。解凍方法は、私が必要としているものに多少近いように見えますが、正確ではありません。

4

2 に答える 2

5

variadic 関数concatenate()は iterable を連結し、シーケンスを生成します。

Integer[] prod(Integer max, Integer occurrences) {
    Integer[][] nestedSequence = [ for (occurrence in 1..occurrences) range(max) ];
    return concatenate(*nestedSequence);
}

これは、次のように簡潔に書き直すことができます。

Integer[] prod(Integer max, Integer occurrences)
        => concatenate(for (occurrence in 1..occurrences) range(max));

しかし、私はこの実装が好きではありません。なぜなら、それはシーケンスの積極的なインスタンス化をたくさん行うからです。私は、シーケンスのインスタンス化を 1 つだけ行うこの実装を非常に好みます。

Integer[] prod4(Integer max, Integer occurrences)
        => [ for (occurrence in 1..occurrences) for (x in range(max)) x ];

参考までに、Ceylon 1.1 では、expand()よりもレイジーな関数が追加されましたconcatenate()

HTH、頑張ってください!

于 2013-12-01T04:15:34.423 に答える
1

あなたのrange関数は、範囲の周りに不必要にシーケンスを作成するため、ここでは役に立ちません。1からまで反復するだけmaxでよく、 によって作成された範囲で直接行うことができます1..max。したがって、 に置き換えるrange(max)と、次のよう1..maxに定義できます。prod

Integer[] prod(Integer max, Integer occurrences)
        => (1..max).repeat(occurrences);

あなたの質問に答えるには、 Gavin's answer がなくconcatenateGavin's answerexpandに記載されているように、次のように使用してフラット化されたシーケンスを生成できます。nestedSequenceIterable.fold()

nestedSequence.fold({}, ({Integer*} f, Integer[] r) => f.chain(r)).sequence;

同等に、

Element[] flattened<Element>(Element[][] nestedSequence) {
    variable {Element*} flattened = {}; // same as f above
    for (Element[] range in nestedSequence) { // range is same as r above
        flattened = flattened.chain(range);
    }
    return flattened.sequence;
}

しかし、内包表記を使った Gavin の最後の実装の方が好きです。に比べてより慣用的なセイロンだと思いfoldます。

于 2013-12-01T03:46:25.010 に答える