你如何在锡兰推平一系列序列?

时间:2013-11-30 16:42:13

标签: sequence ceylon

给定一个序列序列的类型,如何将其转换为单个扁平的序列类型?请考虑以下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文档中摸索着。 unzip method看起来有点接近我的需要,但不完全正确。

2 个答案:

答案 0 :(得分:5)

可变函数concatenate()连接迭代,产生一个序列:

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

但是我不喜欢这个实现,因为它做了很多急切的序列实例化。我很多更喜欢这个实现,它只进行一次序列实例化:

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

仅供参考,在Ceylon 1.1中,添加了expand()函数,该函数比concatenate()更加懒散。

HTH,祝你好运!

答案 1 :(得分:1)

你的range函数在这里没用,因为它不必要地在一个范围内创建一个序列。您只需要从1迭代到max,您就可以直接使用1..max创建的范围来执行此操作。因此,将range(max)替换为1..max,您可以像这样定义prod

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

要回答您的问题,在Gavin's answer中没有提及concatenateexpand的情况下,您可以使用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相比,我认为更像是惯用的锡兰。

相关问题