3

给定一个序列序列类型,如何将其转换为单个扁平序列类型?考虑以下锡兰代码:

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 方法看起来有点接近我的需要,但不完全是。

4

2 回答 2

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,祝你好运!

于 2013-12-01T04:15:34.423 回答
1

您的range函数在这里没有用,因为它不必要地创建了一个范围内的序列。您只需要从 to 迭代1max您可以直接使用由1..max. 因此,替换range(max)1..max,您可以prod这样定义:

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

要回答您的问题,在没有concatenateGavin 的回答expand中提到的情况下,您可以使用这样的方法生成一个扁平序列: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 回答