Как сгладить последовательность последовательностей на Цейлоне?
Учитывая тип, который является Последовательностью Последовательностей, как я могу преобразовать это в единственный, плоский тип Последовательности? Рассмотрим следующий код Цейлона:
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]);
Я впервые экспериментирую с Цейлоном и пробираюсь по учебникам и документации API. Метод распаковки выглядит несколько близко к тому, что мне нужно, но не совсем так.
2 ответа
Вариадическая функция 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 ];
К вашему сведению, на Цейлоне 1.1, expand()
функция была добавлена, которая ленивее, чем concatenate()
,
HTH, удачи!
Ваш range
Функция здесь бесполезна, потому что она без необходимости создает последовательность вокруг диапазона. Вам просто нужно повторить от 1
в max
, и вы можете сделать это непосредственно с диапазоном, созданным 1..max
, Итак, замена range(max)
с 1..max
Вы можете определить prod
как это:
Integer[] prod(Integer max, Integer occurrences)
=> (1..max).repeat(occurrences);
Чтобы ответить на ваш вопрос, при отсутствии concatenate
а также expand
как упоминалось в ответе Гэвина, вы можете получить уплощенную последовательность из nestedSequence
с помощью Iterable.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;
}
Но я предпочитаю последнюю реализацию Гэвина, используя понимания. Мне кажется, что Цейлон более идиоматичен по сравнению с fold
,